diff --git a/make/RunTestsPrebuilt.gmk b/make/RunTestsPrebuilt.gmk index 1cbd8f2273a..1afc152ea89 100644 --- a/make/RunTestsPrebuilt.gmk +++ b/make/RunTestsPrebuilt.gmk @@ -189,8 +189,10 @@ ifeq ($(OPENJDK_TARGET_CPU), x86_64) endif ifeq ($(OPENJDK_TARGET_OS), windows) - FIXPATH := $(BASH) $(TOPDIR)/make/scripts/fixpath.sh exec + FIXPATH_BASE := $(BASH) $(TOPDIR)/make/scripts/fixpath.sh + FIXPATH := $(FIXPATH_BASE) exec else + FIXPATH_BASE := FIXPATH := endif @@ -273,6 +275,7 @@ $(call CreateNewSpec, $(NEW_SPEC), \ MAKE := $(MAKE), \ BASH := $(BASH), \ JIB_JAR := $(JIB_JAR), \ + FIXPATH_BASE := $(FIXPATH_BASE), \ FIXPATH := $(FIXPATH), \ OPENJDK_TARGET_OS := $(OPENJDK_TARGET_OS), \ OPENJDK_TARGET_OS_TYPE := $(OPENJDK_TARGET_OS_TYPE), \ diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index 7a6dfb74168..29b08cf9837 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -168,11 +168,6 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS], DISABLED_WARNINGS="unknown-warning-option unused-parameter unused" - if test "x$OPENJDK_TARGET_OS" = xmacosx; then - # missing-method-return-type triggers in JavaNativeFoundation framework - DISABLED_WARNINGS="$DISABLED_WARNINGS missing-method-return-type" - fi - ;; xlc) diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 524562fa4cd..3b5281f2a8f 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1362,15 +1362,15 @@ var concatObjects = function (o1, o2) { * @param patch Override patch version * @returns {String} The numeric version string */ -var getVersion = function (feature, interim, update, patch) { +var getVersion = function (feature, interim, update, patch, extra1, extra2, extra3) { var version_numbers = getVersionNumbers(); var version = (feature != null ? feature : version_numbers.get("DEFAULT_VERSION_FEATURE")) + "." + (interim != null ? interim : version_numbers.get("DEFAULT_VERSION_INTERIM")) + "." + (update != null ? update : version_numbers.get("DEFAULT_VERSION_UPDATE")) + "." + (patch != null ? patch : version_numbers.get("DEFAULT_VERSION_PATCH")) - + "." + version_numbers.get("DEFAULT_VERSION_EXTRA1") - + "." + version_numbers.get("DEFAULT_VERSION_EXTRA2") - + "." + version_numbers.get("DEFAULT_VERSION_EXTRA3"); + + "." + (extra1 != null ? extra1 : version_numbers.get("DEFAULT_VERSION_EXTRA1")) + + "." + (extra2 != null ? extra2 : version_numbers.get("DEFAULT_VERSION_EXTRA2")) + + "." + (extra3 != null ? extra3 : version_numbers.get("DEFAULT_VERSION_EXTRA3")); while (version.match(".*\\.0$")) { version = version.substring(0, version.length - 2); } diff --git a/make/data/cacerts/soneraclass2ca b/make/data/cacerts/soneraclass2ca deleted file mode 100644 index 43faa5e211d..00000000000 --- a/make/data/cacerts/soneraclass2ca +++ /dev/null @@ -1,26 +0,0 @@ -Owner: CN=Sonera Class2 CA, O=Sonera, C=FI -Issuer: CN=Sonera Class2 CA, O=Sonera, C=FI -Serial number: 1d -Valid from: Fri Apr 06 07:29:40 GMT 2001 until: Tue Apr 06 07:29:40 GMT 2021 -Signature algorithm name: SHA1withRSA -Subject Public Key Algorithm: 2048-bit RSA key -Version: 3 ------BEGIN CERTIFICATE----- -MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP -MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx -MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV -BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o -Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt -5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s -3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej -vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu -8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw -DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG -MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil -zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ -3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD -FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 -Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 -ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M ------END CERTIFICATE----- diff --git a/make/data/charsetmapping/DoubleByte-X.java.template b/make/data/charsetmapping/DoubleByte-X.java.template index d97e2c46f4b..20bc9fdc8de 100644 --- a/make/data/charsetmapping/DoubleByte-X.java.template +++ b/make/data/charsetmapping/DoubleByte-X.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,26 +49,19 @@ public class $NAME_CLZ$ extends Charset } public CharsetDecoder newDecoder() { - initb2c(); - return new DoubleByte.Decoder$DECTYPE$(this, b2c, b2cSB, $B2MIN$, $B2MAX$, $ASCIICOMPATIBLE$); + return new DoubleByte.Decoder$DECTYPE$(this, DecodeHolder.b2c, DecodeHolder.b2cSB, $B2MIN$, $B2MAX$, $ASCIICOMPATIBLE$); } public CharsetEncoder newEncoder() { - initc2b(); - return new DoubleByte.Encoder$ENCTYPE$(this, $ENC_REPLACEMENT$ c2b, c2bIndex, $ASCIICOMPATIBLE$); + return new DoubleByte.Encoder$ENCTYPE$(this, $ENC_REPLACEMENT$ EncodeHolder.c2b, EncodeHolder.c2bIndex, $ASCIICOMPATIBLE$); } - $B2C$ - static char[][] b2c = new char[b2cStr.length][]; - static char[] b2cSB; - private static volatile boolean b2cInitialized = false; + static class DecodeHolder { + $B2C$ + static final char[][] b2c = new char[b2cStr.length][]; + static final char[] b2cSB; - static void initb2c() { - if (b2cInitialized) - return; - synchronized (b2c) { - if (b2cInitialized) - return; + static { for (int i = 0; i < b2cStr.length; i++) { if (b2cStr[i] == null) b2c[i] = DoubleByte.B2C_UNMAPPABLE; @@ -76,26 +69,20 @@ public class $NAME_CLZ$ extends Charset b2c[i] = b2cStr[i].toCharArray(); } b2cSB = b2cSBStr.toCharArray(); - b2cInitialized = true; } } - static char[] c2b = new char[$C2BLENGTH$]; - static char[] c2bIndex = new char[0x100]; - private static volatile boolean c2bInitialized = false; + static class EncodeHolder { + static final char[] c2b = new char[$C2BLENGTH$]; + static final char[] c2bIndex = new char[0x100]; - static void initc2b() { - if (c2bInitialized) - return; - synchronized (c2b) { - if (c2bInitialized) - return; + static { $NONROUNDTRIP_B2C$ $NONROUNDTRIP_C2B$ - DoubleByte.Encoder.initC2B(b2cStr, b2cSBStr, b2cNR, c2bNR, + DoubleByte.Encoder.initC2B(DecodeHolder.b2cStr, DecodeHolder.b2cSBStr, + b2cNR, c2bNR, $B2MIN$, $B2MAX$, c2b, c2bIndex); - c2bInitialized = true; } } } diff --git a/make/data/charsetmapping/SingleByte-X.java.template b/make/data/charsetmapping/SingleByte-X.java.template index 537d218d557..7ef9a59f343 100644 --- a/make/data/charsetmapping/SingleByte-X.java.template +++ b/make/data/charsetmapping/SingleByte-X.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,24 +48,26 @@ public class $NAME_CLZ$ extends Charset implements HistoricallyNamedCharset } public CharsetDecoder newDecoder() { - return new SingleByte.Decoder(this, b2c, $ASCIICOMPATIBLE$, $LATIN1DECODABLE$); + return new SingleByte.Decoder(this, Holder.b2c, $ASCIICOMPATIBLE$, $LATIN1DECODABLE$); } public CharsetEncoder newEncoder() { - return new SingleByte.Encoder(this, c2b, c2bIndex, $ASCIICOMPATIBLE$); + return new SingleByte.Encoder(this, Holder.c2b, Holder.c2bIndex, $ASCIICOMPATIBLE$); } - private final static String b2cTable = $B2CTABLE$ + private static class Holder { + private static final String b2cTable = $B2CTABLE$ - private final static char[] b2c = b2cTable.toCharArray(); - private final static char[] c2b = new char[$C2BLENGTH$]; - private final static char[] c2bIndex = new char[0x100]; + private static final char[] b2c = b2cTable.toCharArray(); + private static final char[] c2b = new char[$C2BLENGTH$]; + private static final char[] c2bIndex = new char[0x100]; - static { - char[] b2cMap = b2c; - char[] c2bNR = null; - $NONROUNDTRIP_B2C$ - $NONROUNDTRIP_C2B$ - SingleByte.initC2B(b2cMap, c2bNR, c2b, c2bIndex); + static { + char[] b2cMap = b2c; + char[] c2bNR = null; + $NONROUNDTRIP_B2C$ + $NONROUNDTRIP_C2B$ + SingleByte.initC2B(b2cMap, c2bNR, c2b, c2bIndex); + } } } diff --git a/make/data/tzdata/VERSION b/make/data/tzdata/VERSION index d946a9fd9fe..71632a7bb61 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. # -tzdata2020f +tzdata2021a diff --git a/make/data/tzdata/africa b/make/data/tzdata/africa index 4b5c9d8aa77..5de2e5f4ab1 100644 --- a/make/data/tzdata/africa +++ b/make/data/tzdata/africa @@ -1550,11 +1550,17 @@ Zone Africa/Khartoum 2:10:08 - LMT 1931 3:00 - EAT 2017 Nov 1 2:00 - CAT +# From Steffen Thorsen (2021-01-18): +# "South Sudan will change its time zone by setting the clock back 1 +# hour on February 1, 2021...." +# from https://eyeradio.org/south-sudan-adopts-new-time-zone-makuei/ + # South Sudan # Zone NAME STDOFF RULES FORMAT [UNTIL] Zone Africa/Juba 2:06:28 - LMT 1931 2:00 Sudan CA%sT 2000 Jan 15 12:00 - 3:00 - EAT + 3:00 - EAT 2021 Feb 1 00:00 + 2:00 - CAT # Tanzania # See Africa/Nairobi. diff --git a/make/data/tzdata/leapseconds b/make/data/tzdata/leapseconds index d5f74194ade..6f1941601d3 100644 --- a/make/data/tzdata/leapseconds +++ b/make/data/tzdata/leapseconds @@ -95,11 +95,11 @@ Leap 2016 Dec 31 23:59:60 + S # Any additional leap seconds will come after this. # This Expires line is commented out for now, # so that pre-2020a zic implementations do not reject this file. -#Expires 2021 Jun 28 00:00:00 +#Expires 2021 Dec 28 00:00:00 # POSIX timestamps for the data in this file: #updated 1467936000 (2016-07-08 00:00:00 UTC) -#expires 1624838400 (2021-06-28 00:00:00 UTC) +#expires 1640649600 (2021-12-28 00:00:00 UTC) -# Updated through IERS Bulletin C60 -# File expires on: 28 June 2021 +# Updated through IERS Bulletin C61 +# File expires on: 28 December 2021 diff --git a/make/modules/java.base/Lib.gmk b/make/modules/java.base/Lib.gmk index 0eff999a011..5658ff342e5 100644 --- a/make/modules/java.base/Lib.gmk +++ b/make/modules/java.base/Lib.gmk @@ -96,8 +96,6 @@ $(BUILD_LIBNIO): $(BUILD_LIBNET) # Create the macosx security library ifeq ($(call isTargetOs, macosx), true) - # JavaNativeFoundation framework not supported in static builds - ifneq ($(STATIC_BUILD), true) $(eval $(call SetupJdkLibrary, BUILD_LIBOSXSECURITY, \ NAME := osxsecurity, \ @@ -120,7 +118,6 @@ ifeq ($(call isTargetOs, macosx), true) TARGETS += $(BUILD_LIBOSXSECURITY) - endif endif ################################################################################ diff --git a/make/modules/java.desktop/Lib.gmk b/make/modules/java.desktop/Lib.gmk index 54b96f56c60..bc0c349da6a 100644 --- a/make/modules/java.desktop/Lib.gmk +++ b/make/modules/java.desktop/Lib.gmk @@ -101,7 +101,6 @@ ifeq ($(call isTargetOs, macosx), true) -framework Cocoa \ -framework Security \ -framework ExceptionHandling \ - -framework JavaNativeFoundation \ -framework JavaRuntimeSupport \ -framework OpenGL \ -framework IOSurface \ @@ -127,7 +126,6 @@ ifeq ($(call isTargetOs, macosx), true) -losxapp \ -framework Cocoa \ -framework ApplicationServices \ - -framework JavaNativeFoundation \ -framework JavaRuntimeSupport \ -framework SystemConfiguration \ $(JDKLIB_LIBS), \ diff --git a/make/modules/java.desktop/lib/Awt2dLibraries.gmk b/make/modules/java.desktop/lib/Awt2dLibraries.gmk index d1e6cc29816..bc862c45bf4 100644 --- a/make/modules/java.desktop/lib/Awt2dLibraries.gmk +++ b/make/modules/java.desktop/lib/Awt2dLibraries.gmk @@ -160,7 +160,6 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \ LIBS_macosx := -lmlib_image \ -framework Cocoa \ -framework OpenGL \ - -framework JavaNativeFoundation \ -framework JavaRuntimeSupport \ -framework ApplicationServices \ -framework AudioToolbox, \ @@ -767,8 +766,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) -framework ApplicationServices \ -framework Foundation \ -framework Security \ - -framework Cocoa \ - -framework JavaNativeFoundation + -framework Cocoa else ifeq ($(call isTargetOs, windows), true) LIBSPLASHSCREEN_LIBS += kernel32.lib user32.lib gdi32.lib delayimp.lib $(WIN_JAVA_LIB) jvm.lib else @@ -866,7 +864,6 @@ ifeq ($(call isTargetOs, macosx), true) -framework Cocoa \ -framework Security \ -framework ExceptionHandling \ - -framework JavaNativeFoundation \ -framework JavaRuntimeSupport \ -framework OpenGL \ -framework QuartzCore -ljava, \ @@ -904,7 +901,6 @@ ifeq ($(call isTargetOs, macosx), true) -framework Cocoa \ -framework Carbon \ -framework ApplicationServices \ - -framework JavaNativeFoundation \ -framework JavaRuntimeSupport \ -ljava -ljvm, \ )) diff --git a/make/modules/jdk.hotspot.agent/Lib.gmk b/make/modules/jdk.hotspot.agent/Lib.gmk index 871dffeeb9e..4c4f88792de 100644 --- a/make/modules/jdk.hotspot.agent/Lib.gmk +++ b/make/modules/jdk.hotspot.agent/Lib.gmk @@ -69,7 +69,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBSA, \ LIBS := $(LIBCXX), \ LIBS_unix := -ljava, \ LIBS_linux := $(LIBDL), \ - LIBS_macosx := -framework Foundation -framework JavaNativeFoundation \ + LIBS_macosx := -framework Foundation \ -framework JavaRuntimeSupport -framework Security -framework CoreFoundation, \ LIBS_windows := dbgeng.lib $(WIN_JAVA_LIB), \ )) diff --git a/make/modules/jdk.jpackage/Lib.gmk b/make/modules/jdk.jpackage/Lib.gmk index 7dfb70be5a6..aa955b97bee 100644 --- a/make/modules/jdk.jpackage/Lib.gmk +++ b/make/modules/jdk.jpackage/Lib.gmk @@ -28,9 +28,17 @@ include LibCommon.gmk ################################################################################ -JPACKAGE_APPLAUNCHER_SRC := \ - $(call FindSrcDirsForComponent, jdk.jpackage, applauncher) \ - $(call FindSrcDirsForComponent, jdk.jpackage, common) +ifeq ($(call isTargetOs, linux), true) + JPACKAGE_APPLAUNCHER_SRC := \ + $(call FindSrcDirsForComponent, jdk.jpackage, applauncher) + JPACKAGE_APPLAUNCHER_TOOLCHAIN := TOOLCHAIN_DEFAULT + JPACKAGE_APPLAUNCHER_INCLUDE_FILES := %.c +else + JPACKAGE_APPLAUNCHER_SRC := \ + $(call FindSrcDirsForComponent, jdk.jpackage, applauncher) \ + $(call FindSrcDirsForComponent, jdk.jpackage, common) + JPACKAGE_APPLAUNCHER_TOOLCHAIN := TOOLCHAIN_LINK_CXX +endif ifeq ($(call isTargetOs, windows), true) @@ -44,6 +52,8 @@ endif JPACKAGE_OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/jpackage/internal/resources JPACKAGE_CXXFLAGS_windows := -EHsc -DUNICODE -D_UNICODE +JPACKAGE_CFLAGS_windows := -DUNICODE -D_UNICODE +JPACKAGE_APPLAUNCHER_INCLUDES := $(addprefix -I, $(JPACKAGE_APPLAUNCHER_SRC)) # Output app launcher executable in resources dir, and symbols in the object dir $(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHEREXE, \ @@ -51,20 +61,54 @@ $(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHEREXE, \ OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \ SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncher, \ SRC := $(JPACKAGE_APPLAUNCHER_SRC), \ - TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ + INCLUDE_FILES := $(JPACKAGE_APPLAUNCHER_INCLUDE_FILES), \ + TOOLCHAIN := $(JPACKAGE_APPLAUNCHER_TOOLCHAIN), \ OPTIMIZATION := LOW, \ CXXFLAGS := $(call JpackageWithStaticCrt, $(CXXFLAGS_JDKEXE)) \ - $(addprefix -I, $(JPACKAGE_APPLAUNCHER_SRC)), \ + $(JPACKAGE_APPLAUNCHER_INCLUDES), \ + CFLAGS := $(call JpackageWithStaticCrt, $(CFLAGS_JDKEXE)) \ + $(JPACKAGE_APPLAUNCHER_INCLUDES), \ + CFLAGS_macosx := -Wno-format-nonliteral, \ CXXFLAGS_windows := $(JPACKAGE_CXXFLAGS_windows), \ + CFLAGS_windows := $(JPACKAGE_CFLAGS_windows), \ LDFLAGS := $(LDFLAGS_JDKEXE), \ - LIBS_macosx := -framework Cocoa, \ - LIBS := $(LIBCXX), \ + LIBS_macosx := $(LIBCXX) -framework Cocoa, \ + LIBS_windows := $(LIBCXX), \ LIBS_linux := -ldl, \ )) -$(BUILD_JPACKAGE_APPLAUNCHEREXE): $(call FindLib, java.base, java) +JPACKAGE_TARGETS += $(BUILD_JPACKAGE_APPLAUNCHEREXE) + + +################################################################################ + +ifeq ($(call isTargetOs, linux), true) + + JPACKAGE_LIBAPPLAUNCHER_SRC := \ + $(call FindSrcDirsForComponent, jdk.jpackage, applauncher) \ + $(call FindSrcDirsForComponent, jdk.jpackage, libapplauncher) \ + $(call FindSrcDirsForComponent, jdk.jpackage, common) + + JPACKAGE_LIBAPPLAUNCHER_INCLUDES := $(addprefix -I, $(JPACKAGE_LIBAPPLAUNCHER_SRC)) + + $(eval $(call SetupJdkLibrary, BUILD_JPACKAGE_LIBAPPLAUNCHER, \ + NAME := jpackageapplauncher, \ + OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \ + SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjpackageapplauncher, \ + SRC := $(JPACKAGE_LIBAPPLAUNCHER_SRC), \ + EXCLUDE_FILES := LinuxLauncher.c LinuxPackage.c, \ + TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ + OPTIMIZATION := LOW, \ + CXXFLAGS := $(CXXFLAGS_JDKLIB) $(JPACKAGE_LIBAPPLAUNCHER_INCLUDES), \ + CFLAGS := $(CFLAGS_JDKLIB) $(JPACKAGE_LIBAPPLAUNCHER_INCLUDES), \ + LDFLAGS := $(LDFLAGS_JDKLIB), \ + LIBS := $(LIBCXX) -ldl, \ + )) + + JPACKAGE_TARGETS += $(BUILD_JPACKAGE_LIBAPPLAUNCHER) + +endif -TARGETS += $(BUILD_JPACKAGE_APPLAUNCHEREXE) ################################################################################ @@ -80,7 +124,7 @@ ifeq ($(call isTargetOs, windows), true) LIBS := $(LIBCXX), \ )) - TARGETS += $(BUILD_LIB_JPACKAGE) + JPACKAGE_TARGETS += $(BUILD_LIB_JPACKAGE) # Build Wix custom action helper # Output library in resources dir, and symbols in the object dir @@ -96,7 +140,7 @@ ifeq ($(call isTargetOs, windows), true) LIBS_windows := msi.lib Shlwapi.lib User32.lib, \ )) - TARGETS += $(BUILD_LIB_WIXHELPER) + JPACKAGE_TARGETS += $(BUILD_LIB_WIXHELPER) JPACKAGE_MSIWRAPPER_SRC := \ $(call FindSrcDirsForComponent, jdk.jpackage, msiwrapper) \ @@ -114,22 +158,30 @@ ifeq ($(call isTargetOs, windows), true) LIBS := $(LIBCXX), \ )) - TARGETS += $(BUILD_JPACKAGE_MSIWRAPPER) + JPACKAGE_TARGETS += $(BUILD_JPACKAGE_MSIWRAPPER) # Build non-console version of launcher $(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHERWEXE, \ - NAME := jpackageapplauncherw, \ - OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \ - SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncherw, \ - SRC := $(BUILD_JPACKAGE_APPLAUNCHEREXE_SRC), \ - TOOLCHAIN := $(BUILD_JPACKAGE_APPLAUNCHEREXE_TOOLCHAIN), \ - OPTIMIZATION := $(BUILD_JPACKAGE_APPLAUNCHEREXE_OPTIMIZATION), \ - CXXFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS), \ - CXXFLAGS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS_windows) -DJP_LAUNCHERW, \ - LDFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LDFLAGS), \ - LIBS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LIBS), \ -)) + NAME := jpackageapplauncherw, \ + OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \ + SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncherw, \ + SRC := $(BUILD_JPACKAGE_APPLAUNCHEREXE_SRC), \ + TOOLCHAIN := $(BUILD_JPACKAGE_APPLAUNCHEREXE_TOOLCHAIN), \ + OPTIMIZATION := $(BUILD_JPACKAGE_APPLAUNCHEREXE_OPTIMIZATION), \ + CXXFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS), \ + CXXFLAGS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS_windows) -DJP_LAUNCHERW, \ + CFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CFLAGS), \ + CFLAGS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CFLAGS_windows) -DJP_LAUNCHERW, \ + LDFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LDFLAGS), \ + LIBS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LIBS), \ + LIBS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LIBS_windows), \ + )) - TARGETS += $(BUILD_JPACKAGE_APPLAUNCHERWEXE) + JPACKAGE_TARGETS += $(BUILD_JPACKAGE_APPLAUNCHERWEXE) endif + + +TARGETS += $(JPACKAGE_TARGETS) + +$(JPACKAGE_TARGETS): $(call FindLib, java.base, java) diff --git a/make/test/JtregNativeJdk.gmk b/make/test/JtregNativeJdk.gmk index 8560ef060a2..3342710bcd2 100644 --- a/make/test/JtregNativeJdk.gmk +++ b/make/test/JtregNativeJdk.gmk @@ -78,7 +78,7 @@ endif ifeq ($(call isTargetOs, macosx), true) BUILD_JDK_JTREG_EXCLUDE += exelauncher.c BUILD_JDK_JTREG_LIBRARIES_LIBS_libTestMainKeyWindow := \ - -framework Cocoa -framework JavaNativeFoundation + -framework Cocoa BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeJniInvocationTest := -ljli BUILD_JDK_JTREG_LIBRARIES_LIBS_libTestDynamicStore := \ -framework Cocoa -framework SystemConfiguration diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 5f00de7aca1..fc188f9f3a3 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -16632,2446 +16632,6 @@ instruct tlsLoadP(thread_RegP dst) ins_pipe(pipe_class_empty); %} -// ====================VECTOR INSTRUCTIONS===================================== - -// Load vector (32 bits) -instruct loadV4(vecD dst, vmem4 mem) -%{ - predicate(n->as_LoadVector()->memory_size() == 4); - match(Set dst (LoadVector mem)); - ins_cost(4 * INSN_COST); - format %{ "ldrs $dst,$mem\t# vector (32 bits)" %} - ins_encode( aarch64_enc_ldrvS(dst, mem) ); - ins_pipe(vload_reg_mem64); -%} - -// Load vector (64 bits) -instruct loadV8(vecD dst, vmem8 mem) -%{ - predicate(n->as_LoadVector()->memory_size() == 8); - match(Set dst (LoadVector mem)); - ins_cost(4 * INSN_COST); - format %{ "ldrd $dst,$mem\t# vector (64 bits)" %} - ins_encode( aarch64_enc_ldrvD(dst, mem) ); - ins_pipe(vload_reg_mem64); -%} - -// Load Vector (128 bits) -instruct loadV16(vecX dst, vmem16 mem) -%{ - predicate(UseSVE == 0 && n->as_LoadVector()->memory_size() == 16); - match(Set dst (LoadVector mem)); - ins_cost(4 * INSN_COST); - format %{ "ldrq $dst,$mem\t# vector (128 bits)" %} - ins_encode( aarch64_enc_ldrvQ(dst, mem) ); - ins_pipe(vload_reg_mem128); -%} - -// Store Vector (32 bits) -instruct storeV4(vecD src, vmem4 mem) -%{ - predicate(n->as_StoreVector()->memory_size() == 4); - match(Set mem (StoreVector mem src)); - ins_cost(4 * INSN_COST); - format %{ "strs $mem,$src\t# vector (32 bits)" %} - ins_encode( aarch64_enc_strvS(src, mem) ); - ins_pipe(vstore_reg_mem64); -%} - -// Store Vector (64 bits) -instruct storeV8(vecD src, vmem8 mem) -%{ - predicate(n->as_StoreVector()->memory_size() == 8); - match(Set mem (StoreVector mem src)); - ins_cost(4 * INSN_COST); - format %{ "strd $mem,$src\t# vector (64 bits)" %} - ins_encode( aarch64_enc_strvD(src, mem) ); - ins_pipe(vstore_reg_mem64); -%} - -// Store Vector (128 bits) -instruct storeV16(vecX src, vmem16 mem) -%{ - predicate(n->as_StoreVector()->memory_size() == 16); - match(Set mem (StoreVector mem src)); - ins_cost(4 * INSN_COST); - format %{ "strq $mem,$src\t# vector (128 bits)" %} - ins_encode( aarch64_enc_strvQ(src, mem) ); - ins_pipe(vstore_reg_mem128); -%} - -instruct replicate8B(vecD dst, iRegIorL2I src) -%{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); - match(Set dst (ReplicateB src)); - ins_cost(INSN_COST); - format %{ "dup $dst, $src\t# vector (8B)" %} - ins_encode %{ - __ dup(as_FloatRegister($dst$$reg), __ T8B, as_Register($src$$reg)); - %} - ins_pipe(vdup_reg_reg64); -%} - -instruct replicate16B(vecX dst, iRegIorL2I src) -%{ - predicate(UseSVE == 0 && n->as_Vector()->length() == 16); - match(Set dst (ReplicateB src)); - ins_cost(INSN_COST); - format %{ "dup $dst, $src\t# vector (16B)" %} - ins_encode %{ - __ dup(as_FloatRegister($dst$$reg), __ T16B, as_Register($src$$reg)); - %} - ins_pipe(vdup_reg_reg128); -%} - -instruct replicate8B_imm(vecD dst, immI con) -%{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); - match(Set dst (ReplicateB con)); - ins_cost(INSN_COST); - format %{ "movi $dst, $con\t# vector(8B)" %} - ins_encode %{ - __ mov(as_FloatRegister($dst$$reg), __ T8B, $con$$constant & 0xff); - %} - ins_pipe(vmovi_reg_imm64); -%} - -instruct replicate16B_imm(vecX dst, immI con) -%{ - predicate(UseSVE == 0 && n->as_Vector()->length() == 16); - match(Set dst (ReplicateB con)); - ins_cost(INSN_COST); - format %{ "movi $dst, $con\t# vector(16B)" %} - ins_encode %{ - __ mov(as_FloatRegister($dst$$reg), __ T16B, $con$$constant & 0xff); - %} - ins_pipe(vmovi_reg_imm128); -%} - -instruct replicate4S(vecD dst, iRegIorL2I src) -%{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); - match(Set dst (ReplicateS src)); - ins_cost(INSN_COST); - format %{ "dup $dst, $src\t# vector (4S)" %} - ins_encode %{ - __ dup(as_FloatRegister($dst$$reg), __ T4H, as_Register($src$$reg)); - %} - ins_pipe(vdup_reg_reg64); -%} - -instruct replicate8S(vecX dst, iRegIorL2I src) -%{ - predicate(UseSVE == 0 && n->as_Vector()->length() == 8); - match(Set dst (ReplicateS src)); - ins_cost(INSN_COST); - format %{ "dup $dst, $src\t# vector (8S)" %} - ins_encode %{ - __ dup(as_FloatRegister($dst$$reg), __ T8H, as_Register($src$$reg)); - %} - ins_pipe(vdup_reg_reg128); -%} - -instruct replicate4S_imm(vecD dst, immI con) -%{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); - match(Set dst (ReplicateS con)); - ins_cost(INSN_COST); - format %{ "movi $dst, $con\t# vector(4H)" %} - ins_encode %{ - __ mov(as_FloatRegister($dst$$reg), __ T4H, $con$$constant & 0xffff); - %} - ins_pipe(vmovi_reg_imm64); -%} - -instruct replicate8S_imm(vecX dst, immI con) -%{ - predicate(UseSVE == 0 && n->as_Vector()->length() == 8); - match(Set dst (ReplicateS con)); - ins_cost(INSN_COST); - format %{ "movi $dst, $con\t# vector(8H)" %} - ins_encode %{ - __ mov(as_FloatRegister($dst$$reg), __ T8H, $con$$constant & 0xffff); - %} - ins_pipe(vmovi_reg_imm128); -%} - -instruct replicate2I(vecD dst, iRegIorL2I src) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (ReplicateI src)); - ins_cost(INSN_COST); - format %{ "dup $dst, $src\t# vector (2I)" %} - ins_encode %{ - __ dup(as_FloatRegister($dst$$reg), __ T2S, as_Register($src$$reg)); - %} - ins_pipe(vdup_reg_reg64); -%} - -instruct replicate4I(vecX dst, iRegIorL2I src) -%{ - predicate(UseSVE == 0 && n->as_Vector()->length() == 4); - match(Set dst (ReplicateI src)); - ins_cost(INSN_COST); - format %{ "dup $dst, $src\t# vector (4I)" %} - ins_encode %{ - __ dup(as_FloatRegister($dst$$reg), __ T4S, as_Register($src$$reg)); - %} - ins_pipe(vdup_reg_reg128); -%} - -instruct replicate2I_imm(vecD dst, immI con) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (ReplicateI con)); - ins_cost(INSN_COST); - format %{ "movi $dst, $con\t# vector(2I)" %} - ins_encode %{ - __ mov(as_FloatRegister($dst$$reg), __ T2S, $con$$constant); - %} - ins_pipe(vmovi_reg_imm64); -%} - -instruct replicate4I_imm(vecX dst, immI con) -%{ - predicate(UseSVE == 0 && n->as_Vector()->length() == 4); - match(Set dst (ReplicateI con)); - ins_cost(INSN_COST); - format %{ "movi $dst, $con\t# vector(4I)" %} - ins_encode %{ - __ mov(as_FloatRegister($dst$$reg), __ T4S, $con$$constant); - %} - ins_pipe(vmovi_reg_imm128); -%} - -instruct replicate2L(vecX dst, iRegL src) -%{ - predicate(UseSVE == 0 && n->as_Vector()->length() == 2); - match(Set dst (ReplicateL src)); - ins_cost(INSN_COST); - format %{ "dup $dst, $src\t# vector (2L)" %} - ins_encode %{ - __ dup(as_FloatRegister($dst$$reg), __ T2D, as_Register($src$$reg)); - %} - ins_pipe(vdup_reg_reg128); -%} - -instruct replicate2L_zero(vecX dst, immI0 zero) -%{ - predicate(UseSVE == 0 && n->as_Vector()->length() == 2); - match(Set dst (ReplicateI zero)); - ins_cost(INSN_COST); - format %{ "movi $dst, $zero\t# vector(4I)" %} - ins_encode %{ - __ eor(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($dst$$reg), - as_FloatRegister($dst$$reg)); - %} - ins_pipe(vmovi_reg_imm128); -%} - -instruct replicate2F(vecD dst, vRegF src) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (ReplicateF src)); - ins_cost(INSN_COST); - format %{ "dup $dst, $src\t# vector (2F)" %} - ins_encode %{ - __ dup(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src$$reg)); - %} - ins_pipe(vdup_reg_freg64); -%} - -instruct replicate4F(vecX dst, vRegF src) -%{ - predicate(UseSVE == 0 && n->as_Vector()->length() == 4); - match(Set dst (ReplicateF src)); - ins_cost(INSN_COST); - format %{ "dup $dst, $src\t# vector (4F)" %} - ins_encode %{ - __ dup(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src$$reg)); - %} - ins_pipe(vdup_reg_freg128); -%} - -instruct replicate2D(vecX dst, vRegD src) -%{ - predicate(UseSVE == 0 && n->as_Vector()->length() == 2); - match(Set dst (ReplicateD src)); - ins_cost(INSN_COST); - format %{ "dup $dst, $src\t# vector (2D)" %} - ins_encode %{ - __ dup(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src$$reg)); - %} - ins_pipe(vdup_reg_dreg128); -%} - -// ====================REDUCTION ARITHMETIC==================================== - -instruct reduce_add2I(iRegINoSp dst, iRegIorL2I isrc, vecD vsrc, iRegINoSp tmp, iRegINoSp tmp2) -%{ - predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); - match(Set dst (AddReductionVI isrc vsrc)); - ins_cost(INSN_COST); - effect(TEMP tmp, TEMP tmp2); - format %{ "umov $tmp, $vsrc, S, 0\n\t" - "umov $tmp2, $vsrc, S, 1\n\t" - "addw $tmp, $isrc, $tmp\n\t" - "addw $dst, $tmp, $tmp2\t# add reduction2I" - %} - ins_encode %{ - __ umov($tmp$$Register, as_FloatRegister($vsrc$$reg), __ S, 0); - __ umov($tmp2$$Register, as_FloatRegister($vsrc$$reg), __ S, 1); - __ addw($tmp$$Register, $isrc$$Register, $tmp$$Register); - __ addw($dst$$Register, $tmp$$Register, $tmp2$$Register); - %} - ins_pipe(pipe_class_default); -%} - -instruct reduce_add4I(iRegINoSp dst, iRegIorL2I isrc, vecX vsrc, vecX vtmp, iRegINoSp itmp) -%{ - predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); - match(Set dst (AddReductionVI isrc vsrc)); - ins_cost(INSN_COST); - effect(TEMP vtmp, TEMP itmp); - format %{ "addv $vtmp, T4S, $vsrc\n\t" - "umov $itmp, $vtmp, S, 0\n\t" - "addw $dst, $itmp, $isrc\t# add reduction4I" - %} - ins_encode %{ - __ addv(as_FloatRegister($vtmp$$reg), __ T4S, - as_FloatRegister($vsrc$$reg)); - __ umov($itmp$$Register, as_FloatRegister($vtmp$$reg), __ S, 0); - __ addw($dst$$Register, $itmp$$Register, $isrc$$Register); - %} - ins_pipe(pipe_class_default); -%} - -instruct reduce_mul2I(iRegINoSp dst, iRegIorL2I isrc, vecD vsrc, iRegINoSp tmp) -%{ - predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); - match(Set dst (MulReductionVI isrc vsrc)); - ins_cost(INSN_COST); - effect(TEMP tmp, TEMP dst); - format %{ "umov $tmp, $vsrc, S, 0\n\t" - "mul $dst, $tmp, $isrc\n\t" - "umov $tmp, $vsrc, S, 1\n\t" - "mul $dst, $tmp, $dst\t# mul reduction2I" - %} - ins_encode %{ - __ umov($tmp$$Register, as_FloatRegister($vsrc$$reg), __ S, 0); - __ mul($dst$$Register, $tmp$$Register, $isrc$$Register); - __ umov($tmp$$Register, as_FloatRegister($vsrc$$reg), __ S, 1); - __ mul($dst$$Register, $tmp$$Register, $dst$$Register); - %} - ins_pipe(pipe_class_default); -%} - -instruct reduce_mul4I(iRegINoSp dst, iRegIorL2I isrc, vecX vsrc, vecX vtmp, iRegINoSp itmp) -%{ - predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); - match(Set dst (MulReductionVI isrc vsrc)); - ins_cost(INSN_COST); - effect(TEMP vtmp, TEMP itmp, TEMP dst); - format %{ "ins $vtmp, D, $vsrc, 0, 1\n\t" - "mulv $vtmp, T2S, $vtmp, $vsrc\n\t" - "umov $itmp, $vtmp, S, 0\n\t" - "mul $dst, $itmp, $isrc\n\t" - "umov $itmp, $vtmp, S, 1\n\t" - "mul $dst, $itmp, $dst\t# mul reduction4I" - %} - ins_encode %{ - __ ins(as_FloatRegister($vtmp$$reg), __ D, - as_FloatRegister($vsrc$$reg), 0, 1); - __ mulv(as_FloatRegister($vtmp$$reg), __ T2S, - as_FloatRegister($vtmp$$reg), as_FloatRegister($vsrc$$reg)); - __ umov($itmp$$Register, as_FloatRegister($vtmp$$reg), __ S, 0); - __ mul($dst$$Register, $itmp$$Register, $isrc$$Register); - __ umov($itmp$$Register, as_FloatRegister($vtmp$$reg), __ S, 1); - __ mul($dst$$Register, $itmp$$Register, $dst$$Register); - %} - ins_pipe(pipe_class_default); -%} - -instruct reduce_add2F(vRegF dst, vRegF fsrc, vecD vsrc, vecD tmp) -%{ - match(Set dst (AddReductionVF fsrc vsrc)); - ins_cost(INSN_COST); - effect(TEMP tmp, TEMP dst); - format %{ "fadds $dst, $fsrc, $vsrc\n\t" - "ins $tmp, S, $vsrc, 0, 1\n\t" - "fadds $dst, $dst, $tmp\t# add reduction2F" - %} - ins_encode %{ - __ fadds(as_FloatRegister($dst$$reg), - as_FloatRegister($fsrc$$reg), as_FloatRegister($vsrc$$reg)); - __ ins(as_FloatRegister($tmp$$reg), __ S, - as_FloatRegister($vsrc$$reg), 0, 1); - __ fadds(as_FloatRegister($dst$$reg), - as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); - %} - ins_pipe(pipe_class_default); -%} - -instruct reduce_add4F(vRegF dst, vRegF fsrc, vecX vsrc, vecX tmp) -%{ - match(Set dst (AddReductionVF fsrc vsrc)); - ins_cost(INSN_COST); - effect(TEMP tmp, TEMP dst); - format %{ "fadds $dst, $fsrc, $vsrc\n\t" - "ins $tmp, S, $vsrc, 0, 1\n\t" - "fadds $dst, $dst, $tmp\n\t" - "ins $tmp, S, $vsrc, 0, 2\n\t" - "fadds $dst, $dst, $tmp\n\t" - "ins $tmp, S, $vsrc, 0, 3\n\t" - "fadds $dst, $dst, $tmp\t# add reduction4F" - %} - ins_encode %{ - __ fadds(as_FloatRegister($dst$$reg), - as_FloatRegister($fsrc$$reg), as_FloatRegister($vsrc$$reg)); - __ ins(as_FloatRegister($tmp$$reg), __ S, - as_FloatRegister($vsrc$$reg), 0, 1); - __ fadds(as_FloatRegister($dst$$reg), - as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); - __ ins(as_FloatRegister($tmp$$reg), __ S, - as_FloatRegister($vsrc$$reg), 0, 2); - __ fadds(as_FloatRegister($dst$$reg), - as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); - __ ins(as_FloatRegister($tmp$$reg), __ S, - as_FloatRegister($vsrc$$reg), 0, 3); - __ fadds(as_FloatRegister($dst$$reg), - as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); - %} - ins_pipe(pipe_class_default); -%} - -instruct reduce_mul2F(vRegF dst, vRegF fsrc, vecD vsrc, vecD tmp) -%{ - match(Set dst (MulReductionVF fsrc vsrc)); - ins_cost(INSN_COST); - effect(TEMP tmp, TEMP dst); - format %{ "fmuls $dst, $fsrc, $vsrc\n\t" - "ins $tmp, S, $vsrc, 0, 1\n\t" - "fmuls $dst, $dst, $tmp\t# mul reduction2F" - %} - ins_encode %{ - __ fmuls(as_FloatRegister($dst$$reg), - as_FloatRegister($fsrc$$reg), as_FloatRegister($vsrc$$reg)); - __ ins(as_FloatRegister($tmp$$reg), __ S, - as_FloatRegister($vsrc$$reg), 0, 1); - __ fmuls(as_FloatRegister($dst$$reg), - as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); - %} - ins_pipe(pipe_class_default); -%} - -instruct reduce_mul4F(vRegF dst, vRegF fsrc, vecX vsrc, vecX tmp) -%{ - match(Set dst (MulReductionVF fsrc vsrc)); - ins_cost(INSN_COST); - effect(TEMP tmp, TEMP dst); - format %{ "fmuls $dst, $fsrc, $vsrc\n\t" - "ins $tmp, S, $vsrc, 0, 1\n\t" - "fmuls $dst, $dst, $tmp\n\t" - "ins $tmp, S, $vsrc, 0, 2\n\t" - "fmuls $dst, $dst, $tmp\n\t" - "ins $tmp, S, $vsrc, 0, 3\n\t" - "fmuls $dst, $dst, $tmp\t# mul reduction4F" - %} - ins_encode %{ - __ fmuls(as_FloatRegister($dst$$reg), - as_FloatRegister($fsrc$$reg), as_FloatRegister($vsrc$$reg)); - __ ins(as_FloatRegister($tmp$$reg), __ S, - as_FloatRegister($vsrc$$reg), 0, 1); - __ fmuls(as_FloatRegister($dst$$reg), - as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); - __ ins(as_FloatRegister($tmp$$reg), __ S, - as_FloatRegister($vsrc$$reg), 0, 2); - __ fmuls(as_FloatRegister($dst$$reg), - as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); - __ ins(as_FloatRegister($tmp$$reg), __ S, - as_FloatRegister($vsrc$$reg), 0, 3); - __ fmuls(as_FloatRegister($dst$$reg), - as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); - %} - ins_pipe(pipe_class_default); -%} - -instruct reduce_add2D(vRegD dst, vRegD dsrc, vecX vsrc, vecX tmp) -%{ - match(Set dst (AddReductionVD dsrc vsrc)); - ins_cost(INSN_COST); - effect(TEMP tmp, TEMP dst); - format %{ "faddd $dst, $dsrc, $vsrc\n\t" - "ins $tmp, D, $vsrc, 0, 1\n\t" - "faddd $dst, $dst, $tmp\t# add reduction2D" - %} - ins_encode %{ - __ faddd(as_FloatRegister($dst$$reg), - as_FloatRegister($dsrc$$reg), as_FloatRegister($vsrc$$reg)); - __ ins(as_FloatRegister($tmp$$reg), __ D, - as_FloatRegister($vsrc$$reg), 0, 1); - __ faddd(as_FloatRegister($dst$$reg), - as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); - %} - ins_pipe(pipe_class_default); -%} - -instruct reduce_mul2D(vRegD dst, vRegD dsrc, vecX vsrc, vecX tmp) -%{ - match(Set dst (MulReductionVD dsrc vsrc)); - ins_cost(INSN_COST); - effect(TEMP tmp, TEMP dst); - format %{ "fmuld $dst, $dsrc, $vsrc\n\t" - "ins $tmp, D, $vsrc, 0, 1\n\t" - "fmuld $dst, $dst, $tmp\t# mul reduction2D" - %} - ins_encode %{ - __ fmuld(as_FloatRegister($dst$$reg), - as_FloatRegister($dsrc$$reg), as_FloatRegister($vsrc$$reg)); - __ ins(as_FloatRegister($tmp$$reg), __ D, - as_FloatRegister($vsrc$$reg), 0, 1); - __ fmuld(as_FloatRegister($dst$$reg), - as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); - %} - ins_pipe(pipe_class_default); -%} - -// ====================VECTOR ARITHMETIC======================================= - -// --------------------------------- ADD -------------------------------------- - -instruct vadd8B(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); - match(Set dst (AddVB src1 src2)); - ins_cost(INSN_COST); - format %{ "addv $dst,$src1,$src2\t# vector (8B)" %} - ins_encode %{ - __ addv(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop64); -%} - -instruct vadd16B(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 16); - match(Set dst (AddVB src1 src2)); - ins_cost(INSN_COST); - format %{ "addv $dst,$src1,$src2\t# vector (16B)" %} - ins_encode %{ - __ addv(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop128); -%} - -instruct vadd4S(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); - match(Set dst (AddVS src1 src2)); - ins_cost(INSN_COST); - format %{ "addv $dst,$src1,$src2\t# vector (4H)" %} - ins_encode %{ - __ addv(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop64); -%} - -instruct vadd8S(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (AddVS src1 src2)); - ins_cost(INSN_COST); - format %{ "addv $dst,$src1,$src2\t# vector (8H)" %} - ins_encode %{ - __ addv(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop128); -%} - -instruct vadd2I(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (AddVI src1 src2)); - ins_cost(INSN_COST); - format %{ "addv $dst,$src1,$src2\t# vector (2S)" %} - ins_encode %{ - __ addv(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop64); -%} - -instruct vadd4I(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (AddVI src1 src2)); - ins_cost(INSN_COST); - format %{ "addv $dst,$src1,$src2\t# vector (4S)" %} - ins_encode %{ - __ addv(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop128); -%} - -instruct vadd2L(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (AddVL src1 src2)); - ins_cost(INSN_COST); - format %{ "addv $dst,$src1,$src2\t# vector (2L)" %} - ins_encode %{ - __ addv(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop128); -%} - -instruct vadd2F(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (AddVF src1 src2)); - ins_cost(INSN_COST); - format %{ "fadd $dst,$src1,$src2\t# vector (2S)" %} - ins_encode %{ - __ fadd(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop_fp64); -%} - -instruct vadd4F(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (AddVF src1 src2)); - ins_cost(INSN_COST); - format %{ "fadd $dst,$src1,$src2\t# vector (4S)" %} - ins_encode %{ - __ fadd(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop_fp128); -%} - -instruct vadd2D(vecX dst, vecX src1, vecX src2) -%{ - match(Set dst (AddVD src1 src2)); - ins_cost(INSN_COST); - format %{ "fadd $dst,$src1,$src2\t# vector (2D)" %} - ins_encode %{ - __ fadd(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop_fp128); -%} - -// --------------------------------- SUB -------------------------------------- - -instruct vsub8B(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); - match(Set dst (SubVB src1 src2)); - ins_cost(INSN_COST); - format %{ "subv $dst,$src1,$src2\t# vector (8B)" %} - ins_encode %{ - __ subv(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop64); -%} - -instruct vsub16B(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 16); - match(Set dst (SubVB src1 src2)); - ins_cost(INSN_COST); - format %{ "subv $dst,$src1,$src2\t# vector (16B)" %} - ins_encode %{ - __ subv(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop128); -%} - -instruct vsub4S(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); - match(Set dst (SubVS src1 src2)); - ins_cost(INSN_COST); - format %{ "subv $dst,$src1,$src2\t# vector (4H)" %} - ins_encode %{ - __ subv(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop64); -%} - -instruct vsub8S(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (SubVS src1 src2)); - ins_cost(INSN_COST); - format %{ "subv $dst,$src1,$src2\t# vector (8H)" %} - ins_encode %{ - __ subv(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop128); -%} - -instruct vsub2I(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (SubVI src1 src2)); - ins_cost(INSN_COST); - format %{ "subv $dst,$src1,$src2\t# vector (2S)" %} - ins_encode %{ - __ subv(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop64); -%} - -instruct vsub4I(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (SubVI src1 src2)); - ins_cost(INSN_COST); - format %{ "subv $dst,$src1,$src2\t# vector (4S)" %} - ins_encode %{ - __ subv(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop128); -%} - -instruct vsub2L(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (SubVL src1 src2)); - ins_cost(INSN_COST); - format %{ "subv $dst,$src1,$src2\t# vector (2L)" %} - ins_encode %{ - __ subv(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop128); -%} - -instruct vsub2F(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (SubVF src1 src2)); - ins_cost(INSN_COST); - format %{ "fsub $dst,$src1,$src2\t# vector (2S)" %} - ins_encode %{ - __ fsub(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop_fp64); -%} - -instruct vsub4F(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (SubVF src1 src2)); - ins_cost(INSN_COST); - format %{ "fsub $dst,$src1,$src2\t# vector (4S)" %} - ins_encode %{ - __ fsub(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop_fp128); -%} - -instruct vsub2D(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (SubVD src1 src2)); - ins_cost(INSN_COST); - format %{ "fsub $dst,$src1,$src2\t# vector (2D)" %} - ins_encode %{ - __ fsub(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop_fp128); -%} - -// --------------------------------- MUL -------------------------------------- - -instruct vmul8B(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); - match(Set dst (MulVB src1 src2)); - ins_cost(INSN_COST); - format %{ "mulv $dst,$src1,$src2\t# vector (8B)" %} - ins_encode %{ - __ mulv(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmul64); -%} - -instruct vmul16B(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 16); - match(Set dst (MulVB src1 src2)); - ins_cost(INSN_COST); - format %{ "mulv $dst,$src1,$src2\t# vector (16B)" %} - ins_encode %{ - __ mulv(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmul128); -%} - -instruct vmul4S(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); - match(Set dst (MulVS src1 src2)); - ins_cost(INSN_COST); - format %{ "mulv $dst,$src1,$src2\t# vector (4H)" %} - ins_encode %{ - __ mulv(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmul64); -%} - -instruct vmul8S(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (MulVS src1 src2)); - ins_cost(INSN_COST); - format %{ "mulv $dst,$src1,$src2\t# vector (8H)" %} - ins_encode %{ - __ mulv(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmul128); -%} - -instruct vmul2I(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (MulVI src1 src2)); - ins_cost(INSN_COST); - format %{ "mulv $dst,$src1,$src2\t# vector (2S)" %} - ins_encode %{ - __ mulv(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmul64); -%} - -instruct vmul4I(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (MulVI src1 src2)); - ins_cost(INSN_COST); - format %{ "mulv $dst,$src1,$src2\t# vector (4S)" %} - ins_encode %{ - __ mulv(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmul128); -%} - -instruct vmul2F(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (MulVF src1 src2)); - ins_cost(INSN_COST); - format %{ "fmul $dst,$src1,$src2\t# vector (2S)" %} - ins_encode %{ - __ fmul(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmuldiv_fp64); -%} - -instruct vmul4F(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (MulVF src1 src2)); - ins_cost(INSN_COST); - format %{ "fmul $dst,$src1,$src2\t# vector (4S)" %} - ins_encode %{ - __ fmul(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmuldiv_fp128); -%} - -instruct vmul2D(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (MulVD src1 src2)); - ins_cost(INSN_COST); - format %{ "fmul $dst,$src1,$src2\t# vector (2D)" %} - ins_encode %{ - __ fmul(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmuldiv_fp128); -%} - -// --------------------------------- MLA -------------------------------------- - -instruct vmla4S(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); - match(Set dst (AddVS dst (MulVS src1 src2))); - ins_cost(INSN_COST); - format %{ "mlav $dst,$src1,$src2\t# vector (4H)" %} - ins_encode %{ - __ mlav(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmla64); -%} - -instruct vmla8S(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (AddVS dst (MulVS src1 src2))); - ins_cost(INSN_COST); - format %{ "mlav $dst,$src1,$src2\t# vector (8H)" %} - ins_encode %{ - __ mlav(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmla128); -%} - -instruct vmla2I(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (AddVI dst (MulVI src1 src2))); - ins_cost(INSN_COST); - format %{ "mlav $dst,$src1,$src2\t# vector (2S)" %} - ins_encode %{ - __ mlav(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmla64); -%} - -instruct vmla4I(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (AddVI dst (MulVI src1 src2))); - ins_cost(INSN_COST); - format %{ "mlav $dst,$src1,$src2\t# vector (4S)" %} - ins_encode %{ - __ mlav(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmla128); -%} - -// dst + src1 * src2 -instruct vmla2F(vecD dst, vecD src1, vecD src2) %{ - predicate(UseFMA && n->as_Vector()->length() == 2); - match(Set dst (FmaVF dst (Binary src1 src2))); - format %{ "fmla $dst,$src1,$src2\t# vector (2S)" %} - ins_cost(INSN_COST); - ins_encode %{ - __ fmla(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmuldiv_fp64); -%} - -// dst + src1 * src2 -instruct vmla4F(vecX dst, vecX src1, vecX src2) %{ - predicate(UseFMA && n->as_Vector()->length() == 4); - match(Set dst (FmaVF dst (Binary src1 src2))); - format %{ "fmla $dst,$src1,$src2\t# vector (4S)" %} - ins_cost(INSN_COST); - ins_encode %{ - __ fmla(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmuldiv_fp128); -%} - -// dst + src1 * src2 -instruct vmla2D(vecX dst, vecX src1, vecX src2) %{ - predicate(UseFMA && n->as_Vector()->length() == 2); - match(Set dst (FmaVD dst (Binary src1 src2))); - format %{ "fmla $dst,$src1,$src2\t# vector (2D)" %} - ins_cost(INSN_COST); - ins_encode %{ - __ fmla(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmuldiv_fp128); -%} - -// --------------------------------- MLS -------------------------------------- - -instruct vmls4S(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); - match(Set dst (SubVS dst (MulVS src1 src2))); - ins_cost(INSN_COST); - format %{ "mlsv $dst,$src1,$src2\t# vector (4H)" %} - ins_encode %{ - __ mlsv(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmla64); -%} - -instruct vmls8S(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (SubVS dst (MulVS src1 src2))); - ins_cost(INSN_COST); - format %{ "mlsv $dst,$src1,$src2\t# vector (8H)" %} - ins_encode %{ - __ mlsv(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmla128); -%} - -instruct vmls2I(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (SubVI dst (MulVI src1 src2))); - ins_cost(INSN_COST); - format %{ "mlsv $dst,$src1,$src2\t# vector (2S)" %} - ins_encode %{ - __ mlsv(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmla64); -%} - -instruct vmls4I(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (SubVI dst (MulVI src1 src2))); - ins_cost(INSN_COST); - format %{ "mlsv $dst,$src1,$src2\t# vector (4S)" %} - ins_encode %{ - __ mlsv(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmla128); -%} - -// dst - src1 * src2 -instruct vmls2F(vecD dst, vecD src1, vecD src2) %{ - predicate(UseFMA && n->as_Vector()->length() == 2); - match(Set dst (FmaVF dst (Binary (NegVF src1) src2))); - match(Set dst (FmaVF dst (Binary src1 (NegVF src2)))); - format %{ "fmls $dst,$src1,$src2\t# vector (2S)" %} - ins_cost(INSN_COST); - ins_encode %{ - __ fmls(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmuldiv_fp64); -%} - -// dst - src1 * src2 -instruct vmls4F(vecX dst, vecX src1, vecX src2) %{ - predicate(UseFMA && n->as_Vector()->length() == 4); - match(Set dst (FmaVF dst (Binary (NegVF src1) src2))); - match(Set dst (FmaVF dst (Binary src1 (NegVF src2)))); - format %{ "fmls $dst,$src1,$src2\t# vector (4S)" %} - ins_cost(INSN_COST); - ins_encode %{ - __ fmls(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmuldiv_fp128); -%} - -// dst - src1 * src2 -instruct vmls2D(vecX dst, vecX src1, vecX src2) %{ - predicate(UseFMA && n->as_Vector()->length() == 2); - match(Set dst (FmaVD dst (Binary (NegVD src1) src2))); - match(Set dst (FmaVD dst (Binary src1 (NegVD src2)))); - format %{ "fmls $dst,$src1,$src2\t# vector (2D)" %} - ins_cost(INSN_COST); - ins_encode %{ - __ fmls(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmuldiv_fp128); -%} - -// --------------- Vector Multiply-Add Shorts into Integer -------------------- - -instruct vmuladdS2I(vecX dst, vecX src1, vecX src2, vecX tmp) %{ - predicate(n->in(1)->bottom_type()->is_vect()->element_basic_type() == T_SHORT); - match(Set dst (MulAddVS2VI src1 src2)); - ins_cost(INSN_COST); - effect(TEMP_DEF dst, TEMP tmp); - format %{ "smullv $tmp, $src1, $src2\t# vector (4H)\n\t" - "smullv $dst, $src1, $src2\t# vector (8H)\n\t" - "addpv $dst, $tmp, $dst\t# vector (4S)\n\t" %} - ins_encode %{ - __ smullv(as_FloatRegister($tmp$$reg), __ T4H, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - __ smullv(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - __ addpv(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($tmp$$reg), - as_FloatRegister($dst$$reg)); - %} - ins_pipe(vmuldiv_fp128); -%} - -// --------------------------------- DIV -------------------------------------- - -instruct vdiv2F(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (DivVF src1 src2)); - ins_cost(INSN_COST); - format %{ "fdiv $dst,$src1,$src2\t# vector (2S)" %} - ins_encode %{ - __ fdiv(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmuldiv_fp64); -%} - -instruct vdiv4F(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (DivVF src1 src2)); - ins_cost(INSN_COST); - format %{ "fdiv $dst,$src1,$src2\t# vector (4S)" %} - ins_encode %{ - __ fdiv(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmuldiv_fp128); -%} - -instruct vdiv2D(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (DivVD src1 src2)); - ins_cost(INSN_COST); - format %{ "fdiv $dst,$src1,$src2\t# vector (2D)" %} - ins_encode %{ - __ fdiv(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vmuldiv_fp128); -%} - -// --------------------------------- SQRT ------------------------------------- - -instruct vsqrt2F(vecD dst, vecD src) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (SqrtVF src)); - format %{ "fsqrt $dst, $src\t# vector (2F)" %} - ins_encode %{ - __ fsqrt(as_FloatRegister($dst$$reg), __ T2S, as_FloatRegister($src$$reg)); - %} - ins_pipe(vunop_fp64); -%} - -instruct vsqrt4F(vecX dst, vecX src) -%{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (SqrtVF src)); - format %{ "fsqrt $dst, $src\t# vector (4F)" %} - ins_encode %{ - __ fsqrt(as_FloatRegister($dst$$reg), __ T4S, as_FloatRegister($src$$reg)); - %} - ins_pipe(vsqrt_fp128); -%} - -instruct vsqrt2D(vecX dst, vecX src) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (SqrtVD src)); - format %{ "fsqrt $dst, $src\t# vector (2D)" %} - ins_encode %{ - __ fsqrt(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src$$reg)); - %} - ins_pipe(vsqrt_fp128); -%} - -// --------------------------------- NEG -------------------------------------- - -instruct vneg2F(vecD dst, vecD src) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (NegVF src)); - ins_cost(INSN_COST * 3); - format %{ "fneg $dst,$src\t# vector (2S)" %} - ins_encode %{ - __ fneg(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src$$reg)); - %} - ins_pipe(vunop_fp64); -%} - -instruct vneg4F(vecX dst, vecX src) -%{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (NegVF src)); - ins_cost(INSN_COST * 3); - format %{ "fneg $dst,$src\t# vector (4S)" %} - ins_encode %{ - __ fneg(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src$$reg)); - %} - ins_pipe(vunop_fp128); -%} - -instruct vneg2D(vecX dst, vecX src) -%{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (NegVD src)); - ins_cost(INSN_COST * 3); - format %{ "fneg $dst,$src\t# vector (2D)" %} - ins_encode %{ - __ fneg(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src$$reg)); - %} - ins_pipe(vunop_fp128); -%} - -// --------------------------------- AND -------------------------------------- - -instruct vand8B(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length_in_bytes() == 4 || - n->as_Vector()->length_in_bytes() == 8); - match(Set dst (AndV src1 src2)); - ins_cost(INSN_COST); - format %{ "and $dst,$src1,$src2\t# vector (8B)" %} - ins_encode %{ - __ andr(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vlogical64); -%} - -instruct vand16B(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length_in_bytes() == 16); - match(Set dst (AndV src1 src2)); - ins_cost(INSN_COST); - format %{ "and $dst,$src1,$src2\t# vector (16B)" %} - ins_encode %{ - __ andr(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vlogical128); -%} - -// --------------------------------- OR --------------------------------------- - -instruct vor8B(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length_in_bytes() == 4 || - n->as_Vector()->length_in_bytes() == 8); - match(Set dst (OrV src1 src2)); - ins_cost(INSN_COST); - format %{ "and $dst,$src1,$src2\t# vector (8B)" %} - ins_encode %{ - __ orr(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vlogical64); -%} - -instruct vor16B(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length_in_bytes() == 16); - match(Set dst (OrV src1 src2)); - ins_cost(INSN_COST); - format %{ "orr $dst,$src1,$src2\t# vector (16B)" %} - ins_encode %{ - __ orr(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vlogical128); -%} - -// --------------------------------- XOR -------------------------------------- - -instruct vxor8B(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length_in_bytes() == 4 || - n->as_Vector()->length_in_bytes() == 8); - match(Set dst (XorV src1 src2)); - ins_cost(INSN_COST); - format %{ "xor $dst,$src1,$src2\t# vector (8B)" %} - ins_encode %{ - __ eor(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vlogical64); -%} - -instruct vxor16B(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length_in_bytes() == 16); - match(Set dst (XorV src1 src2)); - ins_cost(INSN_COST); - format %{ "xor $dst,$src1,$src2\t# vector (16B)" %} - ins_encode %{ - __ eor(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vlogical128); -%} - -// ------------------------------ Shift --------------------------------------- -instruct vshiftcnt8B(vecD dst, iRegIorL2I cnt) %{ - predicate(n->as_Vector()->length_in_bytes() == 4 || - n->as_Vector()->length_in_bytes() == 8); - match(Set dst (LShiftCntV cnt)); - match(Set dst (RShiftCntV cnt)); - format %{ "dup $dst, $cnt\t# shift count vector (8B)" %} - ins_encode %{ - __ dup(as_FloatRegister($dst$$reg), __ T8B, as_Register($cnt$$reg)); - %} - ins_pipe(vdup_reg_reg64); -%} - -instruct vshiftcnt16B(vecX dst, iRegIorL2I cnt) %{ - predicate(n->as_Vector()->length_in_bytes() == 16); - match(Set dst (LShiftCntV cnt)); - match(Set dst (RShiftCntV cnt)); - format %{ "dup $dst, $cnt\t# shift count vector (16B)" %} - ins_encode %{ - __ dup(as_FloatRegister($dst$$reg), __ T16B, as_Register($cnt$$reg)); - %} - ins_pipe(vdup_reg_reg128); -%} - -instruct vsll8B(vecD dst, vecD src, vecD shift) %{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); - match(Set dst (LShiftVB src shift)); - ins_cost(INSN_COST); - format %{ "sshl $dst,$src,$shift\t# vector (8B)" %} - ins_encode %{ - __ sshl(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), - as_FloatRegister($shift$$reg)); - %} - ins_pipe(vshift64); -%} - -instruct vsll16B(vecX dst, vecX src, vecX shift) %{ - predicate(n->as_Vector()->length() == 16); - match(Set dst (LShiftVB src shift)); - ins_cost(INSN_COST); - format %{ "sshl $dst,$src,$shift\t# vector (16B)" %} - ins_encode %{ - __ sshl(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), - as_FloatRegister($shift$$reg)); - %} - ins_pipe(vshift128); -%} - -// Right shifts with vector shift count on aarch64 SIMD are implemented -// as left shift by negative shift count. -// There are two cases for vector shift count. -// -// Case 1: The vector shift count is from replication. -// | | -// LoadVector RShiftCntV -// | / -// RShiftVI -// Note: In inner loop, multiple neg instructions are used, which can be -// moved to outer loop and merge into one neg instruction. -// -// Case 2: The vector shift count is from loading. -// This case isn't supported by middle-end now. But it's supported by -// panama/vectorIntrinsics(JEP 338: Vector API). -// | | -// LoadVector LoadVector -// | / -// RShiftVI -// - -instruct vsra8B(vecD dst, vecD src, vecD shift, vecD tmp) %{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); - match(Set dst (RShiftVB src shift)); - ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "sshl $dst,$src,$tmp\t# vector (8B)" %} - ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, - as_FloatRegister($shift$$reg)); - __ sshl(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); - %} - ins_pipe(vshift64); -%} - -instruct vsra16B(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 16); - match(Set dst (RShiftVB src shift)); - ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "sshl $dst,$src,$tmp\t# vector (16B)" %} - ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, - as_FloatRegister($shift$$reg)); - __ sshl(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); - %} - ins_pipe(vshift128); -%} - -instruct vsrl8B(vecD dst, vecD src, vecD shift, vecD tmp) %{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); - match(Set dst (URShiftVB src shift)); - ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "ushl $dst,$src,$tmp\t# vector (8B)" %} - ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, - as_FloatRegister($shift$$reg)); - __ ushl(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); - %} - ins_pipe(vshift64); -%} - -instruct vsrl16B(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 16); - match(Set dst (URShiftVB src shift)); - ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "ushl $dst,$src,$tmp\t# vector (16B)" %} - ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, - as_FloatRegister($shift$$reg)); - __ ushl(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); - %} - ins_pipe(vshift128); -%} - -instruct vsll8B_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); - match(Set dst (LShiftVB src (LShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "shl $dst, $src, $shift\t# vector (8B)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 8) { - __ eor(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), - as_FloatRegister($src$$reg)); - } else { - __ shl(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), sh); - } - %} - ins_pipe(vshift64_imm); -%} - -instruct vsll16B_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 16); - match(Set dst (LShiftVB src (LShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "shl $dst, $src, $shift\t# vector (16B)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 8) { - __ eor(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), - as_FloatRegister($src$$reg)); - } else { - __ shl(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), sh); - } - %} - ins_pipe(vshift128_imm); -%} - -instruct vsra8B_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); - match(Set dst (RShiftVB src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "sshr $dst, $src, $shift\t# vector (8B)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 8) sh = 7; - __ sshr(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), sh); - %} - ins_pipe(vshift64_imm); -%} - -instruct vsra16B_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 16); - match(Set dst (RShiftVB src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "sshr $dst, $src, $shift\t# vector (16B)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 8) sh = 7; - __ sshr(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), sh); - %} - ins_pipe(vshift128_imm); -%} - -instruct vsrl8B_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 4 || - n->as_Vector()->length() == 8); - match(Set dst (URShiftVB src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "ushr $dst, $src, $shift\t# vector (8B)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 8) { - __ eor(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), - as_FloatRegister($src$$reg)); - } else { - __ ushr(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), sh); - } - %} - ins_pipe(vshift64_imm); -%} - -instruct vsrl16B_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 16); - match(Set dst (URShiftVB src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "ushr $dst, $src, $shift\t# vector (16B)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 8) { - __ eor(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), - as_FloatRegister($src$$reg)); - } else { - __ ushr(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), sh); - } - %} - ins_pipe(vshift128_imm); -%} - -instruct vsll4S(vecD dst, vecD src, vecD shift) %{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); - match(Set dst (LShiftVS src shift)); - ins_cost(INSN_COST); - format %{ "sshl $dst,$src,$shift\t# vector (4H)" %} - ins_encode %{ - __ sshl(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src$$reg), - as_FloatRegister($shift$$reg)); - %} - ins_pipe(vshift64); -%} - -instruct vsll8S(vecX dst, vecX src, vecX shift) %{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (LShiftVS src shift)); - ins_cost(INSN_COST); - format %{ "sshl $dst,$src,$shift\t# vector (8H)" %} - ins_encode %{ - __ sshl(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src$$reg), - as_FloatRegister($shift$$reg)); - %} - ins_pipe(vshift128); -%} - -instruct vsra4S(vecD dst, vecD src, vecD shift, vecD tmp) %{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); - match(Set dst (RShiftVS src shift)); - ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "sshl $dst,$src,$tmp\t# vector (4H)" %} - ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, - as_FloatRegister($shift$$reg)); - __ sshl(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); - %} - ins_pipe(vshift64); -%} - -instruct vsra8S(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (RShiftVS src shift)); - ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "sshl $dst,$src,$tmp\t# vector (8H)" %} - ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, - as_FloatRegister($shift$$reg)); - __ sshl(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); - %} - ins_pipe(vshift128); -%} - -instruct vsrl4S(vecD dst, vecD src, vecD shift, vecD tmp) %{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); - match(Set dst (URShiftVS src shift)); - ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "ushl $dst,$src,$tmp\t# vector (4H)" %} - ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, - as_FloatRegister($shift$$reg)); - __ ushl(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); - %} - ins_pipe(vshift64); -%} - -instruct vsrl8S(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (URShiftVS src shift)); - ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "ushl $dst,$src,$tmp\t# vector (8H)" %} - ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, - as_FloatRegister($shift$$reg)); - __ ushl(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); - %} - ins_pipe(vshift128); -%} - -instruct vsll4S_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); - match(Set dst (LShiftVS src (LShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "shl $dst, $src, $shift\t# vector (4H)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 16) { - __ eor(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), - as_FloatRegister($src$$reg)); - } else { - __ shl(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src$$reg), sh); - } - %} - ins_pipe(vshift64_imm); -%} - -instruct vsll8S_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (LShiftVS src (LShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "shl $dst, $src, $shift\t# vector (8H)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 16) { - __ eor(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), - as_FloatRegister($src$$reg)); - } else { - __ shl(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src$$reg), sh); - } - %} - ins_pipe(vshift128_imm); -%} - -instruct vsra4S_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); - match(Set dst (RShiftVS src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "sshr $dst, $src, $shift\t# vector (4H)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 16) sh = 15; - __ sshr(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src$$reg), sh); - %} - ins_pipe(vshift64_imm); -%} - -instruct vsra8S_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (RShiftVS src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "sshr $dst, $src, $shift\t# vector (8H)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 16) sh = 15; - __ sshr(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src$$reg), sh); - %} - ins_pipe(vshift128_imm); -%} - -instruct vsrl4S_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2 || - n->as_Vector()->length() == 4); - match(Set dst (URShiftVS src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "ushr $dst, $src, $shift\t# vector (4H)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 16) { - __ eor(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), - as_FloatRegister($src$$reg)); - } else { - __ ushr(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src$$reg), sh); - } - %} - ins_pipe(vshift64_imm); -%} - -instruct vsrl8S_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (URShiftVS src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "ushr $dst, $src, $shift\t# vector (8H)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 16) { - __ eor(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), - as_FloatRegister($src$$reg)); - } else { - __ ushr(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src$$reg), sh); - } - %} - ins_pipe(vshift128_imm); -%} - -instruct vsll2I(vecD dst, vecD src, vecD shift) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (LShiftVI src shift)); - ins_cost(INSN_COST); - format %{ "sshl $dst,$src,$shift\t# vector (2S)" %} - ins_encode %{ - __ sshl(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src$$reg), - as_FloatRegister($shift$$reg)); - %} - ins_pipe(vshift64); -%} - -instruct vsll4I(vecX dst, vecX src, vecX shift) %{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (LShiftVI src shift)); - ins_cost(INSN_COST); - format %{ "sshl $dst,$src,$shift\t# vector (4S)" %} - ins_encode %{ - __ sshl(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src$$reg), - as_FloatRegister($shift$$reg)); - %} - ins_pipe(vshift128); -%} - -instruct vsra2I(vecD dst, vecD src, vecD shift, vecD tmp) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (RShiftVI src shift)); - ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "sshl $dst,$src,$tmp\t# vector (2S)" %} - ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, - as_FloatRegister($shift$$reg)); - __ sshl(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); - %} - ins_pipe(vshift64); -%} - -instruct vsra4I(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (RShiftVI src shift)); - ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "sshl $dst,$src,$tmp\t# vector (4S)" %} - ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, - as_FloatRegister($shift$$reg)); - __ sshl(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); - %} - ins_pipe(vshift128); -%} - -instruct vsrl2I(vecD dst, vecD src, vecD shift, vecD tmp) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (URShiftVI src shift)); - ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "ushl $dst,$src,$tmp\t# vector (2S)" %} - ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T8B, - as_FloatRegister($shift$$reg)); - __ ushl(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); - %} - ins_pipe(vshift64); -%} - -instruct vsrl4I(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (URShiftVI src shift)); - ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "ushl $dst,$src,$tmp\t# vector (4S)" %} - ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, - as_FloatRegister($shift$$reg)); - __ ushl(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); - %} - ins_pipe(vshift128); -%} - -instruct vsll2I_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (LShiftVI src (LShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "shl $dst, $src, $shift\t# vector (2S)" %} - ins_encode %{ - __ shl(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift64_imm); -%} - -instruct vsll4I_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (LShiftVI src (LShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "shl $dst, $src, $shift\t# vector (4S)" %} - ins_encode %{ - __ shl(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift128_imm); -%} - -instruct vsra2I_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (RShiftVI src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "sshr $dst, $src, $shift\t# vector (2S)" %} - ins_encode %{ - __ sshr(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift64_imm); -%} - -instruct vsra4I_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (RShiftVI src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "sshr $dst, $src, $shift\t# vector (4S)" %} - ins_encode %{ - __ sshr(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift128_imm); -%} - -instruct vsrl2I_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (URShiftVI src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "ushr $dst, $src, $shift\t# vector (2S)" %} - ins_encode %{ - __ ushr(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift64_imm); -%} - -instruct vsrl4I_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (URShiftVI src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "ushr $dst, $src, $shift\t# vector (4S)" %} - ins_encode %{ - __ ushr(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift128_imm); -%} - -instruct vsll2L(vecX dst, vecX src, vecX shift) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (LShiftVL src shift)); - ins_cost(INSN_COST); - format %{ "sshl $dst,$src,$shift\t# vector (2D)" %} - ins_encode %{ - __ sshl(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src$$reg), - as_FloatRegister($shift$$reg)); - %} - ins_pipe(vshift128); -%} - -instruct vsra2L(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (RShiftVL src shift)); - ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "sshl $dst,$src,$tmp\t# vector (2D)" %} - ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, - as_FloatRegister($shift$$reg)); - __ sshl(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); - %} - ins_pipe(vshift128); -%} - -instruct vsrl2L(vecX dst, vecX src, vecX shift, vecX tmp) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (URShiftVL src shift)); - ins_cost(INSN_COST); - effect(TEMP tmp); - format %{ "negr $tmp,$shift\t" - "ushl $dst,$src,$tmp\t# vector (2D)" %} - ins_encode %{ - __ negr(as_FloatRegister($tmp$$reg), __ T16B, - as_FloatRegister($shift$$reg)); - __ ushl(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src$$reg), - as_FloatRegister($tmp$$reg)); - %} - ins_pipe(vshift128); -%} - -instruct vsll2L_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (LShiftVL src (LShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "shl $dst, $src, $shift\t# vector (2D)" %} - ins_encode %{ - __ shl(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift128_imm); -%} - -instruct vsra2L_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (RShiftVL src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "sshr $dst, $src, $shift\t# vector (2D)" %} - ins_encode %{ - __ sshr(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift128_imm); -%} - -instruct vsrl2L_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (URShiftVL src (RShiftCntV shift))); - ins_cost(INSN_COST); - format %{ "ushr $dst, $src, $shift\t# vector (2D)" %} - ins_encode %{ - __ ushr(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift128_imm); -%} - -instruct vsraa8B_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (AddVB dst (RShiftVB src (RShiftCntV shift)))); - ins_cost(INSN_COST); - format %{ "ssra $dst, $src, $shift\t# vector (8B)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 8) sh = 7; - __ ssra(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), sh); - %} - ins_pipe(vshift64_imm); -%} - -instruct vsraa16B_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 16); - match(Set dst (AddVB dst (RShiftVB src (RShiftCntV shift)))); - ins_cost(INSN_COST); - format %{ "ssra $dst, $src, $shift\t# vector (16B)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 8) sh = 7; - __ ssra(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), sh); - %} - ins_pipe(vshift128_imm); -%} - -instruct vsraa4S_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (AddVS dst (RShiftVS src (RShiftCntV shift)))); - ins_cost(INSN_COST); - format %{ "ssra $dst, $src, $shift\t# vector (4H)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 16) sh = 15; - __ ssra(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src$$reg), sh); - %} - ins_pipe(vshift64_imm); -%} - -instruct vsraa8S_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (AddVS dst (RShiftVS src (RShiftCntV shift)))); - ins_cost(INSN_COST); - format %{ "ssra $dst, $src, $shift\t# vector (8H)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 16) sh = 15; - __ ssra(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src$$reg), sh); - %} - ins_pipe(vshift128_imm); -%} - -instruct vsraa2I_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (AddVI dst (RShiftVI src (RShiftCntV shift)))); - ins_cost(INSN_COST); - format %{ "ssra $dst, $src, $shift\t# vector (2S)" %} - ins_encode %{ - __ ssra(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift64_imm); -%} - -instruct vsraa4I_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (AddVI dst (RShiftVI src (RShiftCntV shift)))); - ins_cost(INSN_COST); - format %{ "ssra $dst, $src, $shift\t# vector (4S)" %} - ins_encode %{ - __ ssra(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift128_imm); -%} - -instruct vsraa2L_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (AddVL dst (RShiftVL src (RShiftCntV shift)))); - ins_cost(INSN_COST); - format %{ "ssra $dst, $src, $shift\t# vector (2D)" %} - ins_encode %{ - __ ssra(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift128_imm); -%} - -instruct vsrla8B_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (AddVB dst (URShiftVB src (RShiftCntV shift)))); - ins_cost(INSN_COST); - format %{ "usra $dst, $src, $shift\t# vector (8B)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 8) { - __ eor(as_FloatRegister($src$$reg), __ T8B, - as_FloatRegister($src$$reg), - as_FloatRegister($src$$reg)); - } else { - __ usra(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg), sh); - } - %} - ins_pipe(vshift64_imm); -%} - -instruct vsrla16B_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 16); - match(Set dst (AddVB dst (URShiftVB src (RShiftCntV shift)))); - ins_cost(INSN_COST); - format %{ "usra $dst, $src, $shift\t# vector (16B)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 8) { - __ eor(as_FloatRegister($src$$reg), __ T16B, - as_FloatRegister($src$$reg), - as_FloatRegister($src$$reg)); - } else { - __ usra(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg), sh); - } - %} - ins_pipe(vshift128_imm); -%} - -instruct vsrla4S_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (AddVS dst (URShiftVS src (RShiftCntV shift)))); - ins_cost(INSN_COST); - format %{ "usra $dst, $src, $shift\t# vector (4H)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 16) { - __ eor(as_FloatRegister($src$$reg), __ T8B, - as_FloatRegister($src$$reg), - as_FloatRegister($src$$reg)); - } else { - __ ushr(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($src$$reg), sh); - } - %} - ins_pipe(vshift64_imm); -%} - -instruct vsrla8S_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 8); - match(Set dst (AddVS dst (URShiftVS src (RShiftCntV shift)))); - ins_cost(INSN_COST); - format %{ "usra $dst, $src, $shift\t# vector (8H)" %} - ins_encode %{ - int sh = (int)$shift$$constant; - if (sh >= 16) { - __ eor(as_FloatRegister($src$$reg), __ T16B, - as_FloatRegister($src$$reg), - as_FloatRegister($src$$reg)); - } else { - __ usra(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($src$$reg), sh); - } - %} - ins_pipe(vshift128_imm); -%} - -instruct vsrla2I_imm(vecD dst, vecD src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (AddVI dst (URShiftVI src (RShiftCntV shift)))); - ins_cost(INSN_COST); - format %{ "usra $dst, $src, $shift\t# vector (2S)" %} - ins_encode %{ - __ usra(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift64_imm); -%} - -instruct vsrla4I_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 4); - match(Set dst (AddVI dst (URShiftVI src (RShiftCntV shift)))); - ins_cost(INSN_COST); - format %{ "usra $dst, $src, $shift\t# vector (4S)" %} - ins_encode %{ - __ usra(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift128_imm); -%} - -instruct vsrla2L_imm(vecX dst, vecX src, immI shift) %{ - predicate(n->as_Vector()->length() == 2); - match(Set dst (AddVL dst (URShiftVL src (RShiftCntV shift)))); - ins_cost(INSN_COST); - format %{ "usra $dst, $src, $shift\t# vector (2D)" %} - ins_encode %{ - __ usra(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src$$reg), - (int)$shift$$constant); - %} - ins_pipe(vshift128_imm); -%} - -instruct vmax2F(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); - match(Set dst (MaxV src1 src2)); - ins_cost(INSN_COST); - format %{ "fmax $dst,$src1,$src2\t# vector (2F)" %} - ins_encode %{ - __ fmax(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop_fp64); -%} - -instruct vmax4F(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 4 && n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); - match(Set dst (MaxV src1 src2)); - ins_cost(INSN_COST); - format %{ "fmax $dst,$src1,$src2\t# vector (4S)" %} - ins_encode %{ - __ fmax(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop_fp128); -%} - -instruct vmax2D(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); - match(Set dst (MaxV src1 src2)); - ins_cost(INSN_COST); - format %{ "fmax $dst,$src1,$src2\t# vector (2D)" %} - ins_encode %{ - __ fmax(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop_fp128); -%} - -instruct vmin2F(vecD dst, vecD src1, vecD src2) -%{ - predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); - match(Set dst (MinV src1 src2)); - ins_cost(INSN_COST); - format %{ "fmin $dst,$src1,$src2\t# vector (2F)" %} - ins_encode %{ - __ fmin(as_FloatRegister($dst$$reg), __ T2S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop_fp64); -%} - -instruct vmin4F(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 4 && n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); - match(Set dst (MinV src1 src2)); - ins_cost(INSN_COST); - format %{ "fmin $dst,$src1,$src2\t# vector (4S)" %} - ins_encode %{ - __ fmin(as_FloatRegister($dst$$reg), __ T4S, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop_fp128); -%} - -instruct vmin2D(vecX dst, vecX src1, vecX src2) -%{ - predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); - match(Set dst (MinV src1 src2)); - ins_cost(INSN_COST); - format %{ "fmin $dst,$src1,$src2\t# vector (2D)" %} - ins_encode %{ - __ fmin(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src1$$reg), - as_FloatRegister($src2$$reg)); - %} - ins_pipe(vdop_fp128); -%} - -instruct vround2D_reg(vecX dst, vecX src, immI rmode) %{ - predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); - match(Set dst (RoundDoubleModeV src rmode)); - format %{ "frint $dst, $src, $rmode" %} - ins_encode %{ - switch ($rmode$$constant) { - case RoundDoubleModeNode::rmode_rint: - __ frintn(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src$$reg)); - break; - case RoundDoubleModeNode::rmode_floor: - __ frintm(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src$$reg)); - break; - case RoundDoubleModeNode::rmode_ceil: - __ frintp(as_FloatRegister($dst$$reg), __ T2D, - as_FloatRegister($src$$reg)); - break; - } - %} - ins_pipe(vdop_fp128); -%} - -instruct vpopcount4I(vecX dst, vecX src) %{ - predicate(UsePopCountInstruction && n->as_Vector()->length() == 4); - match(Set dst (PopCountVI src)); - format %{ - "cnt $dst, $src\t# vector (16B)\n\t" - "uaddlp $dst, $dst\t# vector (16B)\n\t" - "uaddlp $dst, $dst\t# vector (8H)" - %} - ins_encode %{ - __ cnt(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($src$$reg)); - __ uaddlp(as_FloatRegister($dst$$reg), __ T16B, - as_FloatRegister($dst$$reg)); - __ uaddlp(as_FloatRegister($dst$$reg), __ T8H, - as_FloatRegister($dst$$reg)); - %} - ins_pipe(pipe_class_default); -%} - -instruct vpopcount2I(vecD dst, vecD src) %{ - predicate(UsePopCountInstruction && n->as_Vector()->length() == 2); - match(Set dst (PopCountVI src)); - format %{ - "cnt $dst, $src\t# vector (8B)\n\t" - "uaddlp $dst, $dst\t# vector (8B)\n\t" - "uaddlp $dst, $dst\t# vector (4H)" - %} - ins_encode %{ - __ cnt(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($src$$reg)); - __ uaddlp(as_FloatRegister($dst$$reg), __ T8B, - as_FloatRegister($dst$$reg)); - __ uaddlp(as_FloatRegister($dst$$reg), __ T4H, - as_FloatRegister($dst$$reg)); - %} - ins_pipe(pipe_class_default); -%} - //----------PEEPHOLE RULES----------------------------------------------------- // These must follow all instruction definitions as they use the names // defined in the instructions definitions. diff --git a/src/hotspot/cpu/aarch64/aarch64_neon.ad b/src/hotspot/cpu/aarch64/aarch64_neon.ad index 2ed8b9488c7..59aa45c2de1 100644 --- a/src/hotspot/cpu/aarch64/aarch64_neon.ad +++ b/src/hotspot/cpu/aarch64/aarch64_neon.ad @@ -30,7 +30,7 @@ // ------------------------------ Load/store/reinterpret ----------------------- -// Load vector (16 bits) +// Load Vector (16 bits) instruct loadV2(vecD dst, memory mem) %{ predicate(n->as_LoadVector()->memory_size() == 2); @@ -3702,3 +3702,2424 @@ instruct vabd2D(vecX dst, vecX src1, vecX src2) %} ins_pipe(vunop_fp128); %} + +// Load Vector (32 bits) +instruct loadV4(vecD dst, vmem4 mem) +%{ + predicate(n->as_LoadVector()->memory_size() == 4); + match(Set dst (LoadVector mem)); + ins_cost(4 * INSN_COST); + format %{ "ldrs $dst,$mem\t# vector (32 bits)" %} + ins_encode( aarch64_enc_ldrvS(dst, mem) ); + ins_pipe(vload_reg_mem64); +%} + +// Load Vector (64 bits) +instruct loadV8(vecD dst, vmem8 mem) +%{ + predicate(n->as_LoadVector()->memory_size() == 8); + match(Set dst (LoadVector mem)); + ins_cost(4 * INSN_COST); + format %{ "ldrd $dst,$mem\t# vector (64 bits)" %} + ins_encode( aarch64_enc_ldrvD(dst, mem) ); + ins_pipe(vload_reg_mem64); +%} + +// Load Vector (128 bits) +instruct loadV16(vecX dst, vmem16 mem) +%{ + predicate(UseSVE == 0 && n->as_LoadVector()->memory_size() == 16); + match(Set dst (LoadVector mem)); + ins_cost(4 * INSN_COST); + format %{ "ldrq $dst,$mem\t# vector (128 bits)" %} + ins_encode( aarch64_enc_ldrvQ(dst, mem) ); + ins_pipe(vload_reg_mem128); +%} + +// Store Vector (32 bits) +instruct storeV4(vecD src, vmem4 mem) +%{ + predicate(n->as_StoreVector()->memory_size() == 4); + match(Set mem (StoreVector mem src)); + ins_cost(4 * INSN_COST); + format %{ "strs $mem,$src\t# vector (32 bits)" %} + ins_encode( aarch64_enc_strvS(src, mem) ); + ins_pipe(vstore_reg_mem64); +%} + +// Store Vector (64 bits) +instruct storeV8(vecD src, vmem8 mem) +%{ + predicate(n->as_StoreVector()->memory_size() == 8); + match(Set mem (StoreVector mem src)); + ins_cost(4 * INSN_COST); + format %{ "strd $mem,$src\t# vector (64 bits)" %} + ins_encode( aarch64_enc_strvD(src, mem) ); + ins_pipe(vstore_reg_mem64); +%} + +// Store Vector (128 bits) +instruct storeV16(vecX src, vmem16 mem) +%{ + predicate(n->as_StoreVector()->memory_size() == 16); + match(Set mem (StoreVector mem src)); + ins_cost(4 * INSN_COST); + format %{ "strq $mem,$src\t# vector (128 bits)" %} + ins_encode( aarch64_enc_strvQ(src, mem) ); + ins_pipe(vstore_reg_mem128); +%} + +instruct replicate8B(vecD dst, iRegIorL2I src) +%{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (ReplicateB src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (8B)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T8B, as_Register($src$$reg)); + %} + ins_pipe(vdup_reg_reg64); +%} + +instruct replicate16B(vecX dst, iRegIorL2I src) +%{ + predicate(UseSVE == 0 && n->as_Vector()->length() == 16); + match(Set dst (ReplicateB src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (16B)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T16B, as_Register($src$$reg)); + %} + ins_pipe(vdup_reg_reg128); +%} + +instruct replicate8B_imm(vecD dst, immI con) +%{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (ReplicateB con)); + ins_cost(INSN_COST); + format %{ "movi $dst, $con\t# vector (8B)" %} + ins_encode %{ + __ mov(as_FloatRegister($dst$$reg), __ T8B, $con$$constant & 0xff); + %} + ins_pipe(vmovi_reg_imm64); +%} + +instruct replicate16B_imm(vecX dst, immI con) +%{ + predicate(UseSVE == 0 && n->as_Vector()->length() == 16); + match(Set dst (ReplicateB con)); + ins_cost(INSN_COST); + format %{ "movi $dst, $con\t# vector (16B)" %} + ins_encode %{ + __ mov(as_FloatRegister($dst$$reg), __ T16B, $con$$constant & 0xff); + %} + ins_pipe(vmovi_reg_imm128); +%} + +instruct replicate4S(vecD dst, iRegIorL2I src) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (ReplicateS src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (4S)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T4H, as_Register($src$$reg)); + %} + ins_pipe(vdup_reg_reg64); +%} + +instruct replicate8S(vecX dst, iRegIorL2I src) +%{ + predicate(UseSVE == 0 && n->as_Vector()->length() == 8); + match(Set dst (ReplicateS src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (8S)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T8H, as_Register($src$$reg)); + %} + ins_pipe(vdup_reg_reg128); +%} + +instruct replicate4S_imm(vecD dst, immI con) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (ReplicateS con)); + ins_cost(INSN_COST); + format %{ "movi $dst, $con\t# vector (4H)" %} + ins_encode %{ + __ mov(as_FloatRegister($dst$$reg), __ T4H, $con$$constant & 0xffff); + %} + ins_pipe(vmovi_reg_imm64); +%} + +instruct replicate8S_imm(vecX dst, immI con) +%{ + predicate(UseSVE == 0 && n->as_Vector()->length() == 8); + match(Set dst (ReplicateS con)); + ins_cost(INSN_COST); + format %{ "movi $dst, $con\t# vector (8H)" %} + ins_encode %{ + __ mov(as_FloatRegister($dst$$reg), __ T8H, $con$$constant & 0xffff); + %} + ins_pipe(vmovi_reg_imm128); +%} + +instruct replicate2I(vecD dst, iRegIorL2I src) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (ReplicateI src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (2I)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T2S, as_Register($src$$reg)); + %} + ins_pipe(vdup_reg_reg64); +%} + +instruct replicate4I(vecX dst, iRegIorL2I src) +%{ + predicate(UseSVE == 0 && n->as_Vector()->length() == 4); + match(Set dst (ReplicateI src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (4I)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T4S, as_Register($src$$reg)); + %} + ins_pipe(vdup_reg_reg128); +%} + +instruct replicate2I_imm(vecD dst, immI con) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (ReplicateI con)); + ins_cost(INSN_COST); + format %{ "movi $dst, $con\t# vector (2I)" %} + ins_encode %{ + __ mov(as_FloatRegister($dst$$reg), __ T2S, $con$$constant); + %} + ins_pipe(vmovi_reg_imm64); +%} + +instruct replicate4I_imm(vecX dst, immI con) +%{ + predicate(UseSVE == 0 && n->as_Vector()->length() == 4); + match(Set dst (ReplicateI con)); + ins_cost(INSN_COST); + format %{ "movi $dst, $con\t# vector (4I)" %} + ins_encode %{ + __ mov(as_FloatRegister($dst$$reg), __ T4S, $con$$constant); + %} + ins_pipe(vmovi_reg_imm128); +%} + +instruct replicate2L(vecX dst, iRegL src) +%{ + predicate(UseSVE == 0 && n->as_Vector()->length() == 2); + match(Set dst (ReplicateL src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (2L)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T2D, as_Register($src$$reg)); + %} + ins_pipe(vdup_reg_reg128); +%} + +instruct replicate2L_zero(vecX dst, immI0 zero) +%{ + predicate(UseSVE == 0 && n->as_Vector()->length() == 2); + match(Set dst (ReplicateI zero)); + ins_cost(INSN_COST); + format %{ "movi $dst, $zero\t# vector (4I)" %} + ins_encode %{ + __ eor(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg)); + %} + ins_pipe(vmovi_reg_imm128); +%} + +instruct replicate2F(vecD dst, vRegF src) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (ReplicateF src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (2F)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg)); + %} + ins_pipe(vdup_reg_freg64); +%} + +instruct replicate4F(vecX dst, vRegF src) +%{ + predicate(UseSVE == 0 && n->as_Vector()->length() == 4); + match(Set dst (ReplicateF src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (4F)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src$$reg)); + %} + ins_pipe(vdup_reg_freg128); +%} + +instruct replicate2D(vecX dst, vRegD src) +%{ + predicate(UseSVE == 0 && n->as_Vector()->length() == 2); + match(Set dst (ReplicateD src)); + ins_cost(INSN_COST); + format %{ "dup $dst, $src\t# vector (2D)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg)); + %} + ins_pipe(vdup_reg_dreg128); +%} + +// ====================REDUCTION ARITHMETIC==================================== + +instruct reduce_add2I(iRegINoSp dst, iRegIorL2I isrc, vecD vsrc, iRegINoSp tmp, iRegINoSp tmp2) +%{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); + match(Set dst (AddReductionVI isrc vsrc)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP tmp2); + format %{ "umov $tmp, $vsrc, S, 0\n\t" + "umov $tmp2, $vsrc, S, 1\n\t" + "addw $tmp, $isrc, $tmp\n\t" + "addw $dst, $tmp, $tmp2\t# add reduction2I" + %} + ins_encode %{ + __ umov($tmp$$Register, as_FloatRegister($vsrc$$reg), __ S, 0); + __ umov($tmp2$$Register, as_FloatRegister($vsrc$$reg), __ S, 1); + __ addw($tmp$$Register, $isrc$$Register, $tmp$$Register); + __ addw($dst$$Register, $tmp$$Register, $tmp2$$Register); + %} + ins_pipe(pipe_class_default); +%} + +instruct reduce_add4I(iRegINoSp dst, iRegIorL2I isrc, vecX vsrc, vecX vtmp, iRegINoSp itmp) +%{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); + match(Set dst (AddReductionVI isrc vsrc)); + ins_cost(INSN_COST); + effect(TEMP vtmp, TEMP itmp); + format %{ "addv $vtmp, T4S, $vsrc\n\t" + "umov $itmp, $vtmp, S, 0\n\t" + "addw $dst, $itmp, $isrc\t# add reduction4I" + %} + ins_encode %{ + __ addv(as_FloatRegister($vtmp$$reg), __ T4S, + as_FloatRegister($vsrc$$reg)); + __ umov($itmp$$Register, as_FloatRegister($vtmp$$reg), __ S, 0); + __ addw($dst$$Register, $itmp$$Register, $isrc$$Register); + %} + ins_pipe(pipe_class_default); +%} + +instruct reduce_mul2I(iRegINoSp dst, iRegIorL2I isrc, vecD vsrc, iRegINoSp tmp) +%{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); + match(Set dst (MulReductionVI isrc vsrc)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP dst); + format %{ "umov $tmp, $vsrc, S, 0\n\t" + "mul $dst, $tmp, $isrc\n\t" + "umov $tmp, $vsrc, S, 1\n\t" + "mul $dst, $tmp, $dst\t# mul reduction2I" + %} + ins_encode %{ + __ umov($tmp$$Register, as_FloatRegister($vsrc$$reg), __ S, 0); + __ mul($dst$$Register, $tmp$$Register, $isrc$$Register); + __ umov($tmp$$Register, as_FloatRegister($vsrc$$reg), __ S, 1); + __ mul($dst$$Register, $tmp$$Register, $dst$$Register); + %} + ins_pipe(pipe_class_default); +%} + +instruct reduce_mul4I(iRegINoSp dst, iRegIorL2I isrc, vecX vsrc, vecX vtmp, iRegINoSp itmp) +%{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); + match(Set dst (MulReductionVI isrc vsrc)); + ins_cost(INSN_COST); + effect(TEMP vtmp, TEMP itmp, TEMP dst); + format %{ "ins $vtmp, D, $vsrc, 0, 1\n\t" + "mulv $vtmp, T2S, $vtmp, $vsrc\n\t" + "umov $itmp, $vtmp, S, 0\n\t" + "mul $dst, $itmp, $isrc\n\t" + "umov $itmp, $vtmp, S, 1\n\t" + "mul $dst, $itmp, $dst\t# mul reduction4I" + %} + ins_encode %{ + __ ins(as_FloatRegister($vtmp$$reg), __ D, + as_FloatRegister($vsrc$$reg), 0, 1); + __ mulv(as_FloatRegister($vtmp$$reg), __ T2S, + as_FloatRegister($vtmp$$reg), as_FloatRegister($vsrc$$reg)); + __ umov($itmp$$Register, as_FloatRegister($vtmp$$reg), __ S, 0); + __ mul($dst$$Register, $itmp$$Register, $isrc$$Register); + __ umov($itmp$$Register, as_FloatRegister($vtmp$$reg), __ S, 1); + __ mul($dst$$Register, $itmp$$Register, $dst$$Register); + %} + ins_pipe(pipe_class_default); +%} + +instruct reduce_add2F(vRegF dst, vRegF fsrc, vecD vsrc, vecD tmp) +%{ + match(Set dst (AddReductionVF fsrc vsrc)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP dst); + format %{ "fadds $dst, $fsrc, $vsrc\n\t" + "ins $tmp, S, $vsrc, 0, 1\n\t" + "fadds $dst, $dst, $tmp\t# add reduction2F" + %} + ins_encode %{ + __ fadds(as_FloatRegister($dst$$reg), + as_FloatRegister($fsrc$$reg), as_FloatRegister($vsrc$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ S, + as_FloatRegister($vsrc$$reg), 0, 1); + __ fadds(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + %} + ins_pipe(pipe_class_default); +%} + +instruct reduce_add4F(vRegF dst, vRegF fsrc, vecX vsrc, vecX tmp) +%{ + match(Set dst (AddReductionVF fsrc vsrc)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP dst); + format %{ "fadds $dst, $fsrc, $vsrc\n\t" + "ins $tmp, S, $vsrc, 0, 1\n\t" + "fadds $dst, $dst, $tmp\n\t" + "ins $tmp, S, $vsrc, 0, 2\n\t" + "fadds $dst, $dst, $tmp\n\t" + "ins $tmp, S, $vsrc, 0, 3\n\t" + "fadds $dst, $dst, $tmp\t# add reduction4F" + %} + ins_encode %{ + __ fadds(as_FloatRegister($dst$$reg), + as_FloatRegister($fsrc$$reg), as_FloatRegister($vsrc$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ S, + as_FloatRegister($vsrc$$reg), 0, 1); + __ fadds(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ S, + as_FloatRegister($vsrc$$reg), 0, 2); + __ fadds(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ S, + as_FloatRegister($vsrc$$reg), 0, 3); + __ fadds(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + %} + ins_pipe(pipe_class_default); +%} + +instruct reduce_mul2F(vRegF dst, vRegF fsrc, vecD vsrc, vecD tmp) +%{ + match(Set dst (MulReductionVF fsrc vsrc)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP dst); + format %{ "fmuls $dst, $fsrc, $vsrc\n\t" + "ins $tmp, S, $vsrc, 0, 1\n\t" + "fmuls $dst, $dst, $tmp\t# mul reduction2F" + %} + ins_encode %{ + __ fmuls(as_FloatRegister($dst$$reg), + as_FloatRegister($fsrc$$reg), as_FloatRegister($vsrc$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ S, + as_FloatRegister($vsrc$$reg), 0, 1); + __ fmuls(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + %} + ins_pipe(pipe_class_default); +%} + +instruct reduce_mul4F(vRegF dst, vRegF fsrc, vecX vsrc, vecX tmp) +%{ + match(Set dst (MulReductionVF fsrc vsrc)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP dst); + format %{ "fmuls $dst, $fsrc, $vsrc\n\t" + "ins $tmp, S, $vsrc, 0, 1\n\t" + "fmuls $dst, $dst, $tmp\n\t" + "ins $tmp, S, $vsrc, 0, 2\n\t" + "fmuls $dst, $dst, $tmp\n\t" + "ins $tmp, S, $vsrc, 0, 3\n\t" + "fmuls $dst, $dst, $tmp\t# mul reduction4F" + %} + ins_encode %{ + __ fmuls(as_FloatRegister($dst$$reg), + as_FloatRegister($fsrc$$reg), as_FloatRegister($vsrc$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ S, + as_FloatRegister($vsrc$$reg), 0, 1); + __ fmuls(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ S, + as_FloatRegister($vsrc$$reg), 0, 2); + __ fmuls(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ S, + as_FloatRegister($vsrc$$reg), 0, 3); + __ fmuls(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + %} + ins_pipe(pipe_class_default); +%} + +instruct reduce_add2D(vRegD dst, vRegD dsrc, vecX vsrc, vecX tmp) +%{ + match(Set dst (AddReductionVD dsrc vsrc)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP dst); + format %{ "faddd $dst, $dsrc, $vsrc\n\t" + "ins $tmp, D, $vsrc, 0, 1\n\t" + "faddd $dst, $dst, $tmp\t# add reduction2D" + %} + ins_encode %{ + __ faddd(as_FloatRegister($dst$$reg), + as_FloatRegister($dsrc$$reg), as_FloatRegister($vsrc$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ D, + as_FloatRegister($vsrc$$reg), 0, 1); + __ faddd(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + %} + ins_pipe(pipe_class_default); +%} + +instruct reduce_mul2D(vRegD dst, vRegD dsrc, vecX vsrc, vecX tmp) +%{ + match(Set dst (MulReductionVD dsrc vsrc)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP dst); + format %{ "fmuld $dst, $dsrc, $vsrc\n\t" + "ins $tmp, D, $vsrc, 0, 1\n\t" + "fmuld $dst, $dst, $tmp\t# mul reduction2D" + %} + ins_encode %{ + __ fmuld(as_FloatRegister($dst$$reg), + as_FloatRegister($dsrc$$reg), as_FloatRegister($vsrc$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ D, + as_FloatRegister($vsrc$$reg), 0, 1); + __ fmuld(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + %} + ins_pipe(pipe_class_default); +%} + +// ====================VECTOR ARITHMETIC======================================= + +// --------------------------------- ADD -------------------------------------- + +instruct vadd8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (AddVB src1 src2)); + ins_cost(INSN_COST); + format %{ "addv $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ addv(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop64); +%} + +instruct vadd16B(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 16); + match(Set dst (AddVB src1 src2)); + ins_cost(INSN_COST); + format %{ "addv $dst,$src1,$src2\t# vector (16B)" %} + ins_encode %{ + __ addv(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop128); +%} + +instruct vadd4S(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (AddVS src1 src2)); + ins_cost(INSN_COST); + format %{ "addv $dst,$src1,$src2\t# vector (4H)" %} + ins_encode %{ + __ addv(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop64); +%} + +instruct vadd8S(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (AddVS src1 src2)); + ins_cost(INSN_COST); + format %{ "addv $dst,$src1,$src2\t# vector (8H)" %} + ins_encode %{ + __ addv(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop128); +%} + +instruct vadd2I(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVI src1 src2)); + ins_cost(INSN_COST); + format %{ "addv $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ addv(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop64); +%} + +instruct vadd4I(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (AddVI src1 src2)); + ins_cost(INSN_COST); + format %{ "addv $dst,$src1,$src2\t# vector (4S)" %} + ins_encode %{ + __ addv(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop128); +%} + +instruct vadd2L(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVL src1 src2)); + ins_cost(INSN_COST); + format %{ "addv $dst,$src1,$src2\t# vector (2L)" %} + ins_encode %{ + __ addv(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop128); +%} + +instruct vadd2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fadd $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ fadd(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop_fp64); +%} + +instruct vadd4F(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (AddVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fadd $dst,$src1,$src2\t# vector (4S)" %} + ins_encode %{ + __ fadd(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop_fp128); +%} + +instruct vadd2D(vecX dst, vecX src1, vecX src2) +%{ + match(Set dst (AddVD src1 src2)); + ins_cost(INSN_COST); + format %{ "fadd $dst,$src1,$src2\t# vector (2D)" %} + ins_encode %{ + __ fadd(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop_fp128); +%} + +// --------------------------------- SUB -------------------------------------- + +instruct vsub8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (SubVB src1 src2)); + ins_cost(INSN_COST); + format %{ "subv $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ subv(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop64); +%} + +instruct vsub16B(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 16); + match(Set dst (SubVB src1 src2)); + ins_cost(INSN_COST); + format %{ "subv $dst,$src1,$src2\t# vector (16B)" %} + ins_encode %{ + __ subv(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop128); +%} + +instruct vsub4S(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (SubVS src1 src2)); + ins_cost(INSN_COST); + format %{ "subv $dst,$src1,$src2\t# vector (4H)" %} + ins_encode %{ + __ subv(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop64); +%} + +instruct vsub8S(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (SubVS src1 src2)); + ins_cost(INSN_COST); + format %{ "subv $dst,$src1,$src2\t# vector (8H)" %} + ins_encode %{ + __ subv(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop128); +%} + +instruct vsub2I(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (SubVI src1 src2)); + ins_cost(INSN_COST); + format %{ "subv $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ subv(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop64); +%} + +instruct vsub4I(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (SubVI src1 src2)); + ins_cost(INSN_COST); + format %{ "subv $dst,$src1,$src2\t# vector (4S)" %} + ins_encode %{ + __ subv(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop128); +%} + +instruct vsub2L(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (SubVL src1 src2)); + ins_cost(INSN_COST); + format %{ "subv $dst,$src1,$src2\t# vector (2L)" %} + ins_encode %{ + __ subv(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop128); +%} + +instruct vsub2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (SubVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fsub $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ fsub(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop_fp64); +%} + +instruct vsub4F(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (SubVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fsub $dst,$src1,$src2\t# vector (4S)" %} + ins_encode %{ + __ fsub(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop_fp128); +%} + +instruct vsub2D(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (SubVD src1 src2)); + ins_cost(INSN_COST); + format %{ "fsub $dst,$src1,$src2\t# vector (2D)" %} + ins_encode %{ + __ fsub(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop_fp128); +%} + +// --------------------------------- MUL -------------------------------------- + +instruct vmul8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (MulVB src1 src2)); + ins_cost(INSN_COST); + format %{ "mulv $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ mulv(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmul64); +%} + +instruct vmul16B(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 16); + match(Set dst (MulVB src1 src2)); + ins_cost(INSN_COST); + format %{ "mulv $dst,$src1,$src2\t# vector (16B)" %} + ins_encode %{ + __ mulv(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmul128); +%} + +instruct vmul4S(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (MulVS src1 src2)); + ins_cost(INSN_COST); + format %{ "mulv $dst,$src1,$src2\t# vector (4H)" %} + ins_encode %{ + __ mulv(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmul64); +%} + +instruct vmul8S(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (MulVS src1 src2)); + ins_cost(INSN_COST); + format %{ "mulv $dst,$src1,$src2\t# vector (8H)" %} + ins_encode %{ + __ mulv(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmul128); +%} + +instruct vmul2I(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (MulVI src1 src2)); + ins_cost(INSN_COST); + format %{ "mulv $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ mulv(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmul64); +%} + +instruct vmul4I(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (MulVI src1 src2)); + ins_cost(INSN_COST); + format %{ "mulv $dst,$src1,$src2\t# vector (4S)" %} + ins_encode %{ + __ mulv(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmul128); +%} + +instruct vmul2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (MulVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fmul $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ fmul(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp64); +%} + +instruct vmul4F(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (MulVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fmul $dst,$src1,$src2\t# vector (4S)" %} + ins_encode %{ + __ fmul(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + +instruct vmul2D(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (MulVD src1 src2)); + ins_cost(INSN_COST); + format %{ "fmul $dst,$src1,$src2\t# vector (2D)" %} + ins_encode %{ + __ fmul(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + +// --------------------------------- MLA -------------------------------------- + +instruct vmla4S(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (AddVS dst (MulVS src1 src2))); + ins_cost(INSN_COST); + format %{ "mlav $dst,$src1,$src2\t# vector (4H)" %} + ins_encode %{ + __ mlav(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmla64); +%} + +instruct vmla8S(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (AddVS dst (MulVS src1 src2))); + ins_cost(INSN_COST); + format %{ "mlav $dst,$src1,$src2\t# vector (8H)" %} + ins_encode %{ + __ mlav(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmla128); +%} + +instruct vmla2I(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVI dst (MulVI src1 src2))); + ins_cost(INSN_COST); + format %{ "mlav $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ mlav(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmla64); +%} + +instruct vmla4I(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (AddVI dst (MulVI src1 src2))); + ins_cost(INSN_COST); + format %{ "mlav $dst,$src1,$src2\t# vector (4S)" %} + ins_encode %{ + __ mlav(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmla128); +%} + +// dst + src1 * src2 +instruct vmla2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(UseFMA && n->as_Vector()->length() == 2); + match(Set dst (FmaVF dst (Binary src1 src2))); + ins_cost(INSN_COST); + format %{ "fmla $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ fmla(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp64); +%} + +// dst + src1 * src2 +instruct vmla4F(vecX dst, vecX src1, vecX src2) +%{ + predicate(UseFMA && n->as_Vector()->length() == 4); + match(Set dst (FmaVF dst (Binary src1 src2))); + ins_cost(INSN_COST); + format %{ "fmla $dst,$src1,$src2\t# vector (4S)" %} + ins_encode %{ + __ fmla(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + +// dst + src1 * src2 +instruct vmla2D(vecX dst, vecX src1, vecX src2) +%{ + predicate(UseFMA && n->as_Vector()->length() == 2); + match(Set dst (FmaVD dst (Binary src1 src2))); + ins_cost(INSN_COST); + format %{ "fmla $dst,$src1,$src2\t# vector (2D)" %} + ins_encode %{ + __ fmla(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + +// --------------------------------- MLS -------------------------------------- + +instruct vmls4S(vecD dst, vecD src1, vecD src2) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (SubVS dst (MulVS src1 src2))); + ins_cost(INSN_COST); + format %{ "mlsv $dst,$src1,$src2\t# vector (4H)" %} + ins_encode %{ + __ mlsv(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmla64); +%} + +instruct vmls8S(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (SubVS dst (MulVS src1 src2))); + ins_cost(INSN_COST); + format %{ "mlsv $dst,$src1,$src2\t# vector (8H)" %} + ins_encode %{ + __ mlsv(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmla128); +%} + +instruct vmls2I(vecD dst, vecD src1, vecD src2) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (SubVI dst (MulVI src1 src2))); + ins_cost(INSN_COST); + format %{ "mlsv $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ mlsv(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmla64); +%} + +instruct vmls4I(vecX dst, vecX src1, vecX src2) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (SubVI dst (MulVI src1 src2))); + ins_cost(INSN_COST); + format %{ "mlsv $dst,$src1,$src2\t# vector (4S)" %} + ins_encode %{ + __ mlsv(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmla128); +%} + +// dst - src1 * src2 +instruct vmls2F(vecD dst, vecD src1, vecD src2) %{ + predicate(UseFMA && n->as_Vector()->length() == 2); + match(Set dst (FmaVF dst (Binary (NegVF src1) src2))); + match(Set dst (FmaVF dst (Binary src1 (NegVF src2)))); + ins_cost(INSN_COST); + format %{ "fmls $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ fmls(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp64); +%} + +// dst - src1 * src2 +instruct vmls4F(vecX dst, vecX src1, vecX src2) %{ + predicate(UseFMA && n->as_Vector()->length() == 4); + match(Set dst (FmaVF dst (Binary (NegVF src1) src2))); + match(Set dst (FmaVF dst (Binary src1 (NegVF src2)))); + ins_cost(INSN_COST); + format %{ "fmls $dst,$src1,$src2\t# vector (4S)" %} + ins_encode %{ + __ fmls(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + +// dst - src1 * src2 +instruct vmls2D(vecX dst, vecX src1, vecX src2) %{ + predicate(UseFMA && n->as_Vector()->length() == 2); + match(Set dst (FmaVD dst (Binary (NegVD src1) src2))); + match(Set dst (FmaVD dst (Binary src1 (NegVD src2)))); + ins_cost(INSN_COST); + format %{ "fmls $dst,$src1,$src2\t# vector (2D)" %} + ins_encode %{ + __ fmls(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + +// --------------- Vector Multiply-Add Shorts into Integer -------------------- + +instruct vmuladdS2I(vecX dst, vecX src1, vecX src2, vecX tmp) %{ + predicate(n->in(1)->bottom_type()->is_vect()->element_basic_type() == T_SHORT); + match(Set dst (MulAddVS2VI src1 src2)); + ins_cost(INSN_COST); + effect(TEMP_DEF dst, TEMP tmp); + format %{ "smullv $tmp, $src1, $src2\t# vector (4H)\n\t" + "smullv $dst, $src1, $src2\t# vector (8H)\n\t" + "addpv $dst, $tmp, $dst\t# vector (4S)\n\t" %} + ins_encode %{ + __ smullv(as_FloatRegister($tmp$$reg), __ T4H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + __ smullv(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + __ addpv(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($tmp$$reg), + as_FloatRegister($dst$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + +// --------------------------------- DIV -------------------------------------- + +instruct vdiv2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (DivVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fdiv $dst,$src1,$src2\t# vector (2S)" %} + ins_encode %{ + __ fdiv(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp64); +%} + +instruct vdiv4F(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (DivVF src1 src2)); + ins_cost(INSN_COST); + format %{ "fdiv $dst,$src1,$src2\t# vector (4S)" %} + ins_encode %{ + __ fdiv(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + +instruct vdiv2D(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (DivVD src1 src2)); + ins_cost(INSN_COST); + format %{ "fdiv $dst,$src1,$src2\t# vector (2D)" %} + ins_encode %{ + __ fdiv(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + +// --------------------------------- SQRT ------------------------------------- + +instruct vsqrt2F(vecD dst, vecD src) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (SqrtVF src)); + format %{ "fsqrt $dst, $src\t# vector (2F)" %} + ins_encode %{ + __ fsqrt(as_FloatRegister($dst$$reg), __ T2S, as_FloatRegister($src$$reg)); + %} + ins_pipe(vunop_fp64); +%} + +instruct vsqrt4F(vecX dst, vecX src) +%{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (SqrtVF src)); + format %{ "fsqrt $dst, $src\t# vector (4F)" %} + ins_encode %{ + __ fsqrt(as_FloatRegister($dst$$reg), __ T4S, as_FloatRegister($src$$reg)); + %} + ins_pipe(vsqrt_fp128); +%} + +instruct vsqrt2D(vecX dst, vecX src) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (SqrtVD src)); + format %{ "fsqrt $dst, $src\t# vector (2D)" %} + ins_encode %{ + __ fsqrt(as_FloatRegister($dst$$reg), __ T2D, as_FloatRegister($src$$reg)); + %} + ins_pipe(vsqrt_fp128); +%} + +// --------------------------------- NEG -------------------------------------- + +instruct vneg2F(vecD dst, vecD src) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (NegVF src)); + ins_cost(INSN_COST * 3); + format %{ "fneg $dst,$src\t# vector (2S)" %} + ins_encode %{ + __ fneg(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg)); + %} + ins_pipe(vunop_fp64); +%} + +instruct vneg4F(vecX dst, vecX src) +%{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (NegVF src)); + ins_cost(INSN_COST * 3); + format %{ "fneg $dst,$src\t# vector (4S)" %} + ins_encode %{ + __ fneg(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src$$reg)); + %} + ins_pipe(vunop_fp128); +%} + +instruct vneg2D(vecX dst, vecX src) +%{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (NegVD src)); + ins_cost(INSN_COST * 3); + format %{ "fneg $dst,$src\t# vector (2D)" %} + ins_encode %{ + __ fneg(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg)); + %} + ins_pipe(vunop_fp128); +%} + +// --------------------------------- AND -------------------------------------- + +instruct vand8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length_in_bytes() == 4 || + n->as_Vector()->length_in_bytes() == 8); + match(Set dst (AndV src1 src2)); + ins_cost(INSN_COST); + format %{ "and $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ andr(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vlogical64); +%} + +instruct vand16B(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length_in_bytes() == 16); + match(Set dst (AndV src1 src2)); + ins_cost(INSN_COST); + format %{ "and $dst,$src1,$src2\t# vector (16B)" %} + ins_encode %{ + __ andr(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vlogical128); +%} + +// --------------------------------- OR --------------------------------------- + +instruct vor8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length_in_bytes() == 4 || + n->as_Vector()->length_in_bytes() == 8); + match(Set dst (OrV src1 src2)); + ins_cost(INSN_COST); + format %{ "orr $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ orr(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vlogical64); +%} + +instruct vor16B(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length_in_bytes() == 16); + match(Set dst (OrV src1 src2)); + ins_cost(INSN_COST); + format %{ "orr $dst,$src1,$src2\t# vector (16B)" %} + ins_encode %{ + __ orr(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vlogical128); +%} + +// --------------------------------- XOR -------------------------------------- + +instruct vxor8B(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length_in_bytes() == 4 || + n->as_Vector()->length_in_bytes() == 8); + match(Set dst (XorV src1 src2)); + ins_cost(INSN_COST); + format %{ "xor $dst,$src1,$src2\t# vector (8B)" %} + ins_encode %{ + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vlogical64); +%} + +instruct vxor16B(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length_in_bytes() == 16); + match(Set dst (XorV src1 src2)); + ins_cost(INSN_COST); + format %{ "xor $dst,$src1,$src2\t# vector (16B)" %} + ins_encode %{ + __ eor(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vlogical128); +%} + +// ------------------------------ Shift --------------------------------------- + +instruct vshiftcnt8B(vecD dst, iRegIorL2I cnt) %{ + predicate(n->as_Vector()->length_in_bytes() == 4 || + n->as_Vector()->length_in_bytes() == 8); + match(Set dst (LShiftCntV cnt)); + match(Set dst (RShiftCntV cnt)); + format %{ "dup $dst, $cnt\t# shift count vector (8B)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T8B, as_Register($cnt$$reg)); + %} + ins_pipe(vdup_reg_reg64); +%} + +instruct vshiftcnt16B(vecX dst, iRegIorL2I cnt) %{ + predicate(n->as_Vector()->length_in_bytes() == 16); + match(Set dst (LShiftCntV cnt)); + match(Set dst (RShiftCntV cnt)); + format %{ "dup $dst, $cnt\t# shift count vector (16B)" %} + ins_encode %{ + __ dup(as_FloatRegister($dst$$reg), __ T16B, as_Register($cnt$$reg)); + %} + ins_pipe(vdup_reg_reg128); +%} + +instruct vsll8B(vecD dst, vecD src, vecD shift) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (LShiftVB src shift)); + ins_cost(INSN_COST); + format %{ "sshl $dst,$src,$shift\t# vector (8B)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsll16B(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 16); + match(Set dst (LShiftVB src shift)); + ins_cost(INSN_COST); + format %{ "sshl $dst,$src,$shift\t# vector (16B)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift128); +%} + +// Right shifts with vector shift count on aarch64 SIMD are implemented +// as left shift by negative shift count. +// There are two cases for vector shift count. +// +// Case 1: The vector shift count is from replication. +// | | +// LoadVector RShiftCntV +// | / +// RShiftVI +// Note: In inner loop, multiple neg instructions are used, which can be +// moved to outer loop and merge into one neg instruction. +// +// Case 2: The vector shift count is from loading. +// This case isn't supported by middle-end now. But it's supported by +// panama/vectorIntrinsics(JEP 338: Vector API). +// | | +// LoadVector LoadVector +// | / +// RShiftVI +// + +instruct vsra8B(vecD dst, vecD src, vecD shift, vecD tmp) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (RShiftVB src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "negr $tmp,$shift\t" + "sshl $dst,$src,$tmp\t# vector (8B)" %} + ins_encode %{ + __ negr(as_FloatRegister($tmp$$reg), __ T8B, + as_FloatRegister($shift$$reg)); + __ sshl(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsra16B(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 16); + match(Set dst (RShiftVB src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "negr $tmp,$shift\t" + "sshl $dst,$src,$tmp\t# vector (16B)" %} + ins_encode %{ + __ negr(as_FloatRegister($tmp$$reg), __ T16B, + as_FloatRegister($shift$$reg)); + __ sshl(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsrl8B(vecD dst, vecD src, vecD shift, vecD tmp) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (URShiftVB src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "negr $tmp,$shift\t" + "ushl $dst,$src,$tmp\t# vector (8B)" %} + ins_encode %{ + __ negr(as_FloatRegister($tmp$$reg), __ T8B, + as_FloatRegister($shift$$reg)); + __ ushl(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsrl16B(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 16); + match(Set dst (URShiftVB src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "negr $tmp,$shift\t" + "ushl $dst,$src,$tmp\t# vector (16B)" %} + ins_encode %{ + __ negr(as_FloatRegister($tmp$$reg), __ T16B, + as_FloatRegister($shift$$reg)); + __ ushl(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsll8B_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (LShiftVB src (LShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "shl $dst, $src, $shift\t# vector (8B)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 8) { + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ shl(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(vshift64_imm); +%} + +instruct vsll16B_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 16); + match(Set dst (LShiftVB src (LShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "shl $dst, $src, $shift\t# vector (16B)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 8) { + __ eor(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ shl(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(vshift128_imm); +%} + +instruct vsra8B_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (RShiftVB src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "sshr $dst, $src, $shift\t# vector (8B)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 8) sh = 7; + __ sshr(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), sh); + %} + ins_pipe(vshift64_imm); +%} + +instruct vsra16B_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 16); + match(Set dst (RShiftVB src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "sshr $dst, $src, $shift\t# vector (16B)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 8) sh = 7; + __ sshr(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg), sh); + %} + ins_pipe(vshift128_imm); +%} + +instruct vsrl8B_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8); + match(Set dst (URShiftVB src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "ushr $dst, $src, $shift\t# vector (8B)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 8) { + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ ushr(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(vshift64_imm); +%} + +instruct vsrl16B_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 16); + match(Set dst (URShiftVB src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "ushr $dst, $src, $shift\t# vector (16B)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 8) { + __ eor(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ ushr(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(vshift128_imm); +%} + +instruct vsll4S(vecD dst, vecD src, vecD shift) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (LShiftVS src shift)); + ins_cost(INSN_COST); + format %{ "sshl $dst,$src,$shift\t# vector (4H)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsll8S(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (LShiftVS src shift)); + ins_cost(INSN_COST); + format %{ "sshl $dst,$src,$shift\t# vector (8H)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsra4S(vecD dst, vecD src, vecD shift, vecD tmp) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (RShiftVS src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "negr $tmp,$shift\t" + "sshl $dst,$src,$tmp\t# vector (4H)" %} + ins_encode %{ + __ negr(as_FloatRegister($tmp$$reg), __ T8B, + as_FloatRegister($shift$$reg)); + __ sshl(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsra8S(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (RShiftVS src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "negr $tmp,$shift\t" + "sshl $dst,$src,$tmp\t# vector (8H)" %} + ins_encode %{ + __ negr(as_FloatRegister($tmp$$reg), __ T16B, + as_FloatRegister($shift$$reg)); + __ sshl(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsrl4S(vecD dst, vecD src, vecD shift, vecD tmp) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (URShiftVS src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "negr $tmp,$shift\t" + "ushl $dst,$src,$tmp\t# vector (4H)" %} + ins_encode %{ + __ negr(as_FloatRegister($tmp$$reg), __ T8B, + as_FloatRegister($shift$$reg)); + __ ushl(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsrl8S(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (URShiftVS src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "negr $tmp,$shift\t" + "ushl $dst,$src,$tmp\t# vector (8H)" %} + ins_encode %{ + __ negr(as_FloatRegister($tmp$$reg), __ T16B, + as_FloatRegister($shift$$reg)); + __ ushl(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsll4S_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (LShiftVS src (LShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "shl $dst, $src, $shift\t# vector (4H)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 16) { + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ shl(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(vshift64_imm); +%} + +instruct vsll8S_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (LShiftVS src (LShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "shl $dst, $src, $shift\t# vector (8H)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 16) { + __ eor(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ shl(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(vshift128_imm); +%} + +instruct vsra4S_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (RShiftVS src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "sshr $dst, $src, $shift\t# vector (4H)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 16) sh = 15; + __ sshr(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), sh); + %} + ins_pipe(vshift64_imm); +%} + +instruct vsra8S_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (RShiftVS src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "sshr $dst, $src, $shift\t# vector (8H)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 16) sh = 15; + __ sshr(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src$$reg), sh); + %} + ins_pipe(vshift128_imm); +%} + +instruct vsrl4S_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4); + match(Set dst (URShiftVS src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "ushr $dst, $src, $shift\t# vector (4H)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 16) { + __ eor(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ ushr(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(vshift64_imm); +%} + +instruct vsrl8S_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (URShiftVS src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "ushr $dst, $src, $shift\t# vector (8H)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 16) { + __ eor(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ ushr(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(vshift128_imm); +%} + +instruct vsll2I(vecD dst, vecD src, vecD shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVI src shift)); + ins_cost(INSN_COST); + format %{ "sshl $dst,$src,$shift\t# vector (2S)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsll4I(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (LShiftVI src shift)); + ins_cost(INSN_COST); + format %{ "sshl $dst,$src,$shift\t# vector (4S)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsra2I(vecD dst, vecD src, vecD shift, vecD tmp) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (RShiftVI src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "negr $tmp,$shift\t" + "sshl $dst,$src,$tmp\t# vector (2S)" %} + ins_encode %{ + __ negr(as_FloatRegister($tmp$$reg), __ T8B, + as_FloatRegister($shift$$reg)); + __ sshl(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsra4I(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (RShiftVI src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "negr $tmp,$shift\t" + "sshl $dst,$src,$tmp\t# vector (4S)" %} + ins_encode %{ + __ negr(as_FloatRegister($tmp$$reg), __ T16B, + as_FloatRegister($shift$$reg)); + __ sshl(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsrl2I(vecD dst, vecD src, vecD shift, vecD tmp) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (URShiftVI src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "negr $tmp,$shift\t" + "ushl $dst,$src,$tmp\t# vector (2S)" %} + ins_encode %{ + __ negr(as_FloatRegister($tmp$$reg), __ T8B, + as_FloatRegister($shift$$reg)); + __ ushl(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift64); +%} + +instruct vsrl4I(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (URShiftVI src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "negr $tmp,$shift\t" + "ushl $dst,$src,$tmp\t# vector (4S)" %} + ins_encode %{ + __ negr(as_FloatRegister($tmp$$reg), __ T16B, + as_FloatRegister($shift$$reg)); + __ ushl(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsll2I_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVI src (LShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "shl $dst, $src, $shift\t# vector (2S)" %} + ins_encode %{ + __ shl(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift64_imm); +%} + +instruct vsll4I_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (LShiftVI src (LShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "shl $dst, $src, $shift\t# vector (4S)" %} + ins_encode %{ + __ shl(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift128_imm); +%} + +instruct vsra2I_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (RShiftVI src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "sshr $dst, $src, $shift\t# vector (2S)" %} + ins_encode %{ + __ sshr(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift64_imm); +%} + +instruct vsra4I_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (RShiftVI src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "sshr $dst, $src, $shift\t# vector (4S)" %} + ins_encode %{ + __ sshr(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift128_imm); +%} + +instruct vsrl2I_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (URShiftVI src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "ushr $dst, $src, $shift\t# vector (2S)" %} + ins_encode %{ + __ ushr(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift64_imm); +%} + +instruct vsrl4I_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (URShiftVI src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "ushr $dst, $src, $shift\t# vector (4S)" %} + ins_encode %{ + __ ushr(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift128_imm); +%} + +instruct vsll2L(vecX dst, vecX src, vecX shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVL src shift)); + ins_cost(INSN_COST); + format %{ "sshl $dst,$src,$shift\t# vector (2D)" %} + ins_encode %{ + __ sshl(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsra2L(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (RShiftVL src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "negr $tmp,$shift\t" + "sshl $dst,$src,$tmp\t# vector (2D)" %} + ins_encode %{ + __ negr(as_FloatRegister($tmp$$reg), __ T16B, + as_FloatRegister($shift$$reg)); + __ sshl(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsrl2L(vecX dst, vecX src, vecX shift, vecX tmp) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (URShiftVL src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "negr $tmp,$shift\t" + "ushl $dst,$src,$tmp\t# vector (2D)" %} + ins_encode %{ + __ negr(as_FloatRegister($tmp$$reg), __ T16B, + as_FloatRegister($shift$$reg)); + __ ushl(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift128); +%} + +instruct vsll2L_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (LShiftVL src (LShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "shl $dst, $src, $shift\t# vector (2D)" %} + ins_encode %{ + __ shl(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift128_imm); +%} + +instruct vsra2L_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (RShiftVL src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "sshr $dst, $src, $shift\t# vector (2D)" %} + ins_encode %{ + __ sshr(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift128_imm); +%} + +instruct vsrl2L_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (URShiftVL src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "ushr $dst, $src, $shift\t# vector (2D)" %} + ins_encode %{ + __ ushr(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift128_imm); +%} + +instruct vsraa8B_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (AddVB dst (RShiftVB src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "ssra $dst, $src, $shift\t# vector (8B)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 8) sh = 7; + __ ssra(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), sh); + %} + ins_pipe(vshift64_imm); +%} + +instruct vsraa16B_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 16); + match(Set dst (AddVB dst (RShiftVB src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "ssra $dst, $src, $shift\t# vector (16B)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 8) sh = 7; + __ ssra(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg), sh); + %} + ins_pipe(vshift128_imm); +%} + +instruct vsraa4S_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (AddVS dst (RShiftVS src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "ssra $dst, $src, $shift\t# vector (4H)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 16) sh = 15; + __ ssra(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), sh); + %} + ins_pipe(vshift64_imm); +%} + +instruct vsraa8S_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (AddVS dst (RShiftVS src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "ssra $dst, $src, $shift\t# vector (8H)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh >= 16) sh = 15; + __ ssra(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src$$reg), sh); + %} + ins_pipe(vshift128_imm); +%} + +instruct vsraa2I_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVI dst (RShiftVI src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "ssra $dst, $src, $shift\t# vector (2S)" %} + ins_encode %{ + __ ssra(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift64_imm); +%} + +instruct vsraa4I_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (AddVI dst (RShiftVI src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "ssra $dst, $src, $shift\t# vector (4S)" %} + ins_encode %{ + __ ssra(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift128_imm); +%} + +instruct vsraa2L_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVL dst (RShiftVL src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "ssra $dst, $src, $shift\t# vector (2D)" %} + ins_encode %{ + __ ssra(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift128_imm); +%} + +instruct vsrla8B_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (AddVB dst (URShiftVB src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "usra $dst, $src, $shift\t# vector (8B)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh < 8) { + __ usra(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(vshift64_imm); +%} + +instruct vsrla16B_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 16); + match(Set dst (AddVB dst (URShiftVB src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "usra $dst, $src, $shift\t# vector (16B)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh < 8) { + __ usra(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(vshift128_imm); +%} + +instruct vsrla4S_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (AddVS dst (URShiftVS src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "usra $dst, $src, $shift\t# vector (4H)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh < 16) { + __ usra(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(vshift64_imm); +%} + +instruct vsrla8S_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 8); + match(Set dst (AddVS dst (URShiftVS src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "usra $dst, $src, $shift\t# vector (8H)" %} + ins_encode %{ + int sh = (int)$shift$$constant; + if (sh < 16) { + __ usra(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src$$reg), sh); + } + %} + ins_pipe(vshift128_imm); +%} + +instruct vsrla2I_imm(vecD dst, vecD src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVI dst (URShiftVI src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "usra $dst, $src, $shift\t# vector (2S)" %} + ins_encode %{ + __ usra(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift64_imm); +%} + +instruct vsrla4I_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 4); + match(Set dst (AddVI dst (URShiftVI src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "usra $dst, $src, $shift\t# vector (4S)" %} + ins_encode %{ + __ usra(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift128_imm); +%} + +instruct vsrla2L_imm(vecX dst, vecX src, immI shift) %{ + predicate(n->as_Vector()->length() == 2); + match(Set dst (AddVL dst (URShiftVL src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "usra $dst, $src, $shift\t# vector (2D)" %} + ins_encode %{ + __ usra(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg), + (int)$shift$$constant); + %} + ins_pipe(vshift128_imm); +%} + +instruct vmax2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); + match(Set dst (MaxV src1 src2)); + ins_cost(INSN_COST); + format %{ "fmax $dst,$src1,$src2\t# vector (2F)" %} + ins_encode %{ + __ fmax(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop_fp64); +%} + +instruct vmax4F(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 4 && n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); + match(Set dst (MaxV src1 src2)); + ins_cost(INSN_COST); + format %{ "fmax $dst,$src1,$src2\t# vector (4S)" %} + ins_encode %{ + __ fmax(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop_fp128); +%} + +instruct vmax2D(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); + match(Set dst (MaxV src1 src2)); + ins_cost(INSN_COST); + format %{ "fmax $dst,$src1,$src2\t# vector (2D)" %} + ins_encode %{ + __ fmax(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop_fp128); +%} + +instruct vmin2F(vecD dst, vecD src1, vecD src2) +%{ + predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); + match(Set dst (MinV src1 src2)); + ins_cost(INSN_COST); + format %{ "fmin $dst,$src1,$src2\t# vector (2F)" %} + ins_encode %{ + __ fmin(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop_fp64); +%} + +instruct vmin4F(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 4 && n->bottom_type()->is_vect()->element_basic_type() == T_FLOAT); + match(Set dst (MinV src1 src2)); + ins_cost(INSN_COST); + format %{ "fmin $dst,$src1,$src2\t# vector (4S)" %} + ins_encode %{ + __ fmin(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop_fp128); +%} + +instruct vmin2D(vecX dst, vecX src1, vecX src2) +%{ + predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); + match(Set dst (MinV src1 src2)); + ins_cost(INSN_COST); + format %{ "fmin $dst,$src1,$src2\t# vector (2D)" %} + ins_encode %{ + __ fmin(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop_fp128); +%} + +instruct vround2D_reg(vecX dst, vecX src, immI rmode) %{ + predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); + match(Set dst (RoundDoubleModeV src rmode)); + format %{ "frint $dst, $src, $rmode" %} + ins_encode %{ + switch ($rmode$$constant) { + case RoundDoubleModeNode::rmode_rint: + __ frintn(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg)); + break; + case RoundDoubleModeNode::rmode_floor: + __ frintm(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg)); + break; + case RoundDoubleModeNode::rmode_ceil: + __ frintp(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg)); + break; + } + %} + ins_pipe(vdop_fp128); +%} + +instruct vpopcount4I(vecX dst, vecX src) %{ + predicate(UsePopCountInstruction && n->as_Vector()->length() == 4); + match(Set dst (PopCountVI src)); + format %{ + "cnt $dst, $src\t# vector (16B)\n\t" + "uaddlp $dst, $dst\t# vector (16B)\n\t" + "uaddlp $dst, $dst\t# vector (8H)" + %} + ins_encode %{ + __ cnt(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($src$$reg)); + __ uaddlp(as_FloatRegister($dst$$reg), __ T16B, + as_FloatRegister($dst$$reg)); + __ uaddlp(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($dst$$reg)); + %} + ins_pipe(pipe_class_default); +%} + +instruct vpopcount2I(vecD dst, vecD src) %{ + predicate(UsePopCountInstruction && n->as_Vector()->length() == 2); + match(Set dst (PopCountVI src)); + format %{ + "cnt $dst, $src\t# vector (8B)\n\t" + "uaddlp $dst, $dst\t# vector (8B)\n\t" + "uaddlp $dst, $dst\t# vector (4H)" + %} + ins_encode %{ + __ cnt(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($src$$reg)); + __ uaddlp(as_FloatRegister($dst$$reg), __ T8B, + as_FloatRegister($dst$$reg)); + __ uaddlp(as_FloatRegister($dst$$reg), __ T4H, + as_FloatRegister($dst$$reg)); + %} + ins_pipe(pipe_class_default); +%} diff --git a/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 index eb484637b25..0918114ff76 100644 --- a/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_neon_ad.m4 @@ -57,28 +57,20 @@ dnl // ====================VECTOR INSTRUCTIONS================================== // ------------------------------ Load/store/reinterpret ----------------------- - -// Load vector (16 bits) -instruct loadV2(vecD dst, memory mem) -%{ - predicate(n->as_LoadVector()->memory_size() == 2); - match(Set dst (LoadVector mem)); - ins_cost(4 * INSN_COST); - format %{ "ldrh $dst,$mem\t# vector (16 bits)" %} - ins_encode( aarch64_enc_ldrvH(dst, mem) ); - ins_pipe(vload_reg_mem64); -%} - -// Store Vector (16 bits) -instruct storeV2(vecD src, memory mem) +define(`VLoadStore', ` +// ifelse(load, $3, Load, Store) Vector ($6 bits) +instruct $3V$4`'(vec$5 $7, ifelse($4, 2, memory, vmem$4) mem) %{ - predicate(n->as_StoreVector()->memory_size() == 2); - match(Set mem (StoreVector mem src)); + predicate($8`n->as_'ifelse(load, $3, Load, Store)Vector()->memory_size() == $4); + match(Set ifelse(load, $3, dst (LoadVector mem), mem (StoreVector mem src))); ins_cost(4 * INSN_COST); - format %{ "strh $mem,$src\t# vector (16 bits)" %} - ins_encode( aarch64_enc_strvH(src, mem) ); - ins_pipe(vstore_reg_mem64); -%} + format %{ "$1 ifelse(load, $3, `$dst,$mem', `$mem,$src')\t# vector ($6 bits)" %} + ins_encode( `aarch64_enc_'ifelse(load, $3, ldr, str)v$2($7, mem) ); + ins_pipe(v$3`_reg_mem'ifelse(eval($4 * 8), 128, 128, 64)); +%}')dnl +dnl $1 $2 $3 $4 $5 $6 $7 $8 +VLoadStore(ldrh, H, load, 2, D, 16, dst, ) +VLoadStore(strh, H, store, 2, D, 16, src, ) dnl define(`REINTERPRET', ` instruct reinterpret$1`'(vec$1 dst) @@ -1507,3 +1499,795 @@ VFABD(fabd, fabd, 2, F, D, S, 64) VFABD(fabd, fabd, 4, F, X, S, 128) VFABD(fabd, fabd, 2, D, X, D, 128) dnl +VLoadStore(ldrs, S, load, 4, D, 32, dst, ) +VLoadStore(ldrd, D, load, 8, D, 64, dst, ) +VLoadStore(ldrq, Q, load, 16, X, 128, dst, UseSVE == 0 && ) +VLoadStore(strs, S, store, 4, D, 32, src, ) +VLoadStore(strd, D, store, 8, D, 64, src, ) +VLoadStore(strq, Q, store, 16, X, 128, src, ) +dnl +define(`VREPLICATE', ` +instruct replicate$3$4$5`'(vec$6 dst, $7 ifelse($7, immI0, zero, $7, immI, con, src)) +%{ + predicate(ifelse($8, UseSVE == 0 && , $8, + $8, , , $8` + ')n->as_Vector()->length() == $3); + match(Set dst (Replicate`'ifelse($7, immI0, I, $4) ifelse($7, immI0, zero, $7, immI, con, $7, zero, I, src))); + ins_cost(INSN_COST); + format %{ "$1 $dst, $ifelse($7, immI0, zero, $7, immI, con, src)`\t# vector ('ifelse($4$7, SimmI, $3H, $2, eor, 4I, $3$4)`)"' %} + ins_encode %{ + __ $2(as_FloatRegister($dst$$reg), __ ifelse( + $2, eor, T16B, T$3`'$9),ifelse( + `$4 $7', `B immI', ` '$con$$constant & 0xff, + `$4 $7', `S immI', ` '$con$$constant & 0xffff, + `$4 $7', `I immI', ` '$con$$constant, + `$2', eor,` + as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg)', + `$7', vRegF,` + as_FloatRegister($src$$reg)', + `$7', vRegD,` + as_FloatRegister($src$$reg)', + ` 'as_Register($src$$reg))); + %} + ins_pipe(ifelse($7, immI0, v$1_reg_imm, + $7, immI, v$1_reg_imm, + $7, iRegIorL2I, v$1_reg_reg, + $7, zero, vmovi_reg_imm, + $7, iRegL, vdup_reg_reg, + $4, F, vdup_reg_freg, vdup_reg_dreg)`'ifelse($6, X, 128, 64)); +%}')dnl +dnl $1 $2 $3 $4 $5 $6 $7 $8 $9 +VREPLICATE(dup, dup, 8, B, , D, iRegIorL2I, n->as_Vector()->length() == 4 ||, B) +VREPLICATE(dup, dup, 16, B, , X, iRegIorL2I, UseSVE == 0 && , B) +VREPLICATE(movi, mov, 8, B, _imm, D, immI, n->as_Vector()->length() == 4 ||, B) +VREPLICATE(movi, mov, 16, B, _imm, X, immI, UseSVE == 0 && , B) +VREPLICATE(dup, dup, 4, S, , D, iRegIorL2I, n->as_Vector()->length() == 2 ||, H) +VREPLICATE(dup, dup, 8, S, , X, iRegIorL2I, UseSVE == 0 && , H) +VREPLICATE(movi, mov, 4, S, _imm, D, immI, n->as_Vector()->length() == 2 ||, H) +VREPLICATE(movi, mov, 8, S, _imm, X, immI, UseSVE == 0 && , H) +VREPLICATE(dup, dup, 2, I, , D, iRegIorL2I, , S) +VREPLICATE(dup, dup, 4, I, , X, iRegIorL2I, UseSVE == 0 && , S) +VREPLICATE(movi, mov, 2, I, _imm, D, immI, , S) +VREPLICATE(movi, mov, 4, I, _imm, X, immI, UseSVE == 0 && , S) +VREPLICATE(dup, dup, 2, L, , X, iRegL, UseSVE == 0 && , D) +VREPLICATE(movi, eor, 2, L, _zero, X, immI0, UseSVE == 0 && , D) +VREPLICATE(dup, dup, 2, F, , D, vRegF, , S) +VREPLICATE(dup, dup, 4, F, , X, vRegF, UseSVE == 0 && , S) +VREPLICATE(dup, dup, 2, D, , X, vRegD, UseSVE == 0 && , D) +dnl + +// ====================REDUCTION ARITHMETIC==================================== +dnl +define(`REDUCE_ADD_INT', ` +instruct reduce_add$1$2`'(iRegINoSp dst, iRegIorL2I isrc, vec$3 vsrc, ifelse($1, 2, iRegINoSp tmp, vecX vtmp), iRegINoSp ifelse($1, 2, tmp2, itmp)) +%{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); + match(Set dst (AddReductionVI isrc vsrc)); + ins_cost(INSN_COST); + effect(TEMP ifelse($1, 2, tmp, vtmp), TEMP ifelse($1, 2, tmp2, itmp)); + format %{ ifelse($1, 2, `"umov $tmp, $vsrc, S, 0\n\t" + "umov $tmp2, $vsrc, S, 1\n\t" + "addw $tmp, $isrc, $tmp\n\t" + "addw $dst, $tmp, $tmp2\t# add reduction2I"',`"addv $vtmp, T4S, $vsrc\n\t" + "umov $itmp, $vtmp, S, 0\n\t" + "addw $dst, $itmp, $isrc\t# add reduction4I"') + %} + ins_encode %{ + ifelse($1, 2, `__ umov($tmp$$Register, as_FloatRegister($vsrc$$reg), __ S, 0); + __ umov($tmp2$$Register, as_FloatRegister($vsrc$$reg), __ S, 1); + __ addw($tmp$$Register, $isrc$$Register, $tmp$$Register); + __ addw($dst$$Register, $tmp$$Register, $tmp2$$Register);', `__ addv(as_FloatRegister($vtmp$$reg), __ T4S, + as_FloatRegister($vsrc$$reg)); + __ umov($itmp$$Register, as_FloatRegister($vtmp$$reg), __ S, 0); + __ addw($dst$$Register, $itmp$$Register, $isrc$$Register);') + %} + ins_pipe(pipe_class_default); +%}')dnl +dnl $1 $2 $3 +REDUCE_ADD_INT(2, I, D) +REDUCE_ADD_INT(4, I, X) +dnl +define(`REDUCE_MUL_INT', ` +instruct reduce_mul$1$2`'(iRegINoSp dst, iRegIorL2I isrc, vec$3 vsrc, ifelse($1, 2, iRegINoSp tmp`)', vecX vtmp`,' iRegINoSp itmp`)') +%{ + predicate(n->in(2)->bottom_type()->is_vect()->element_basic_type() == T_INT); + match(Set dst (MulReductionVI isrc vsrc)); + ins_cost(INSN_COST); + effect(TEMP ifelse($1, 2, tmp, vtmp), TEMP ifelse($1, 2, dst, itmp`,' TEMP dst)); + format %{ ifelse($1, 2, `"umov $tmp, $vsrc, S, 0\n\t" + "mul $dst, $tmp, $isrc\n\t" + "umov $tmp, $vsrc, S, 1\n\t" + "mul $dst, $tmp, $dst\t# mul reduction2I"',`"ins $vtmp, D, $vsrc, 0, 1\n\t" + "mulv $vtmp, T2S, $vtmp, $vsrc\n\t" + "umov $itmp, $vtmp, S, 0\n\t" + "mul $dst, $itmp, $isrc\n\t" + "umov $itmp, $vtmp, S, 1\n\t" + "mul $dst, $itmp, $dst\t# mul reduction4I"') + %} + ins_encode %{ + ifelse($1, 2, `__ umov($tmp$$Register, as_FloatRegister($vsrc$$reg), __ S, 0); + __ mul($dst$$Register, $tmp$$Register, $isrc$$Register); + __ umov($tmp$$Register, as_FloatRegister($vsrc$$reg), __ S, 1); + __ mul($dst$$Register, $tmp$$Register, $dst$$Register);', `__ ins(as_FloatRegister($vtmp$$reg), __ D, + as_FloatRegister($vsrc$$reg), 0, 1); + __ mulv(as_FloatRegister($vtmp$$reg), __ T2S, + as_FloatRegister($vtmp$$reg), as_FloatRegister($vsrc$$reg)); + __ umov($itmp$$Register, as_FloatRegister($vtmp$$reg), __ S, 0); + __ mul($dst$$Register, $itmp$$Register, $isrc$$Register); + __ umov($itmp$$Register, as_FloatRegister($vtmp$$reg), __ S, 1); + __ mul($dst$$Register, $itmp$$Register, $dst$$Register);') + %} + ins_pipe(pipe_class_default); +%}')dnl +dnl $1 $2 $3 +REDUCE_MUL_INT(2, I, D) +REDUCE_MUL_INT(4, I, X) +dnl +define(`REDUCE_MULORADD_FORD', ` +instruct reduce_$6$2$3`'(vReg$3 dst, vReg$3 $4src, vec$5 vsrc, vec$5 tmp) +%{ + match(Set dst (ifelse($6, add, Add, Mul)ReductionV$3 $4src vsrc)); + ins_cost(INSN_COST); + effect(TEMP tmp, TEMP dst); + format %{ "$1 $dst, $$4src, $vsrc\n\t" + "ins $tmp, ifelse($3, F, S, D), $vsrc, 0, 1\n\t" + ifelse($2, 2, `"$1 $dst, $dst, $tmp\t# $6 reduction$2$3"', + `"$1 $dst, $dst, $tmp\n\t" + "ins $tmp, S, $vsrc, 0, 2\n\t" + "$1 $dst, $dst, $tmp\n\t" + "ins $tmp, S, $vsrc, 0, 3\n\t" + "$1 $dst, $dst, $tmp\t# $6 reduction4F"') + %} + ins_encode %{ + __ $1(as_FloatRegister($dst$$reg), + as_FloatRegister($$4src$$reg), as_FloatRegister($vsrc$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ ifelse($3, F, S, D), + as_FloatRegister($vsrc$$reg), 0, 1); + __ $1(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg));ifelse($2, 4, ` + __ ins(as_FloatRegister($tmp$$reg), __ ifelse($3, F, S, D), + as_FloatRegister($vsrc$$reg), 0, 2); + __ $1(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg)); + __ ins(as_FloatRegister($tmp$$reg), __ S, + as_FloatRegister($vsrc$$reg), 0, 3); + __ $1(as_FloatRegister($dst$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($tmp$$reg));') + %} + ins_pipe(pipe_class_default); +%}')dnl +dnl $1 $2 $3 $4 $5 $6 +REDUCE_MULORADD_FORD(fadds, 2, F, f, D, add) +REDUCE_MULORADD_FORD(fadds, 4, F, f, X, add) +REDUCE_MULORADD_FORD(fmuls, 2, F, f, D, mul) +REDUCE_MULORADD_FORD(fmuls, 4, F, f, X, mul) +REDUCE_MULORADD_FORD(faddd, 2, D, d, X, add) +REDUCE_MULORADD_FORD(fmuld, 2, D, d, X, mul) + +// ====================VECTOR ARITHMETIC======================================= + +// --------------------------------- ADD -------------------------------------- +define(`VADD', ` +instruct vadd$2$3`'(vec$4 dst, vec$4 src1, vec$4 src2) +%{ifelse($2$3, 8B, ` + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8);', + $2$3, 4S, ` + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4);', + $2$5, 2D, , ` + predicate(n->as_Vector()->length() == $2);') + match(Set dst (AddV$3 src1 src2)); + ins_cost(INSN_COST); + format %{ "$1 $dst,$src1,$src2\t# vector ($2$5)" %} + ins_encode %{ + __ $1(as_FloatRegister($dst$$reg), __ T$2`'ifelse($5, L, D, $5), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop`'ifelse($3, F, _fp, $3, D, _fp)`'ifelse($4, D, 64, 128)); +%}')dnl +dnl $1 $2 $3 $4 $5 +VADD(addv, 8, B, D, B) +VADD(addv, 16, B, X, B) +VADD(addv, 4, S, D, H) +VADD(addv, 8, S, X, H) +VADD(addv, 2, I, D, S) +VADD(addv, 4, I, X, S) +VADD(addv, 2, L, X, L) +VADD(fadd, 2, F, D, S) +VADD(fadd, 4, F, X, S) +VADD(fadd, 2, D, X, D) + +// --------------------------------- SUB -------------------------------------- +define(`VSUB', ` +instruct vsub$2$3`'(vec$4 dst, vec$4 src1, vec$4 src2) +%{ifelse($2$3, 8B, ` + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8);', + $2$3, 4S, ` + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4);',` + predicate(n->as_Vector()->length() == $2);') + match(Set dst (SubV$3 src1 src2)); + ins_cost(INSN_COST); + format %{ "$1 $dst,$src1,$src2\t# vector ($2$5)" %} + ins_encode %{ + __ $1(as_FloatRegister($dst$$reg), __ T$2`'ifelse($5, L, D, $5), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop`'ifelse($3, F, _fp, $3, D, _fp)`'ifelse($4, D, 64, 128)); +%}')dnl +dnl $1 $2 $3 $4 $5 +VSUB(subv, 8, B, D, B) +VSUB(subv, 16, B, X, B) +VSUB(subv, 4, S, D, H) +VSUB(subv, 8, S, X, H) +VSUB(subv, 2, I, D, S) +VSUB(subv, 4, I, X, S) +VSUB(subv, 2, L, X, L) +VSUB(fsub, 2, F, D, S) +VSUB(fsub, 4, F, X, S) +VSUB(fsub, 2, D, X, D) + +// --------------------------------- MUL -------------------------------------- +define(`VMUL', ` +instruct vmul$2$3`'(vec$4 dst, vec$4 src1, vec$4 src2) +%{ifelse($2$3, 8B, ` + predicate(n->as_Vector()->length() == 4 || + n->as_Vector()->length() == 8);', + $2$3, 4S, ` + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4);',` + predicate(n->as_Vector()->length() == $2);') + match(Set dst (MulV$3 src1 src2)); + ins_cost(INSN_COST); + format %{ "$1 $dst,$src1,$src2\t# vector ($2$5)" %} + ins_encode %{ + __ $1(as_FloatRegister($dst$$reg), __ T$2`'ifelse($5, L, D, $5), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmul`'ifelse($3, F, div_fp, $3, D, div_fp)`'ifelse($4, D, 64, 128)); +%}')dnl +dnl $1 $2 $3 $4 $5 +VMUL(mulv, 8, B, D, B) +VMUL(mulv, 16, B, X, B) +VMUL(mulv, 4, S, D, H) +VMUL(mulv, 8, S, X, H) +VMUL(mulv, 2, I, D, S) +VMUL(mulv, 4, I, X, S) +VMUL(fmul, 2, F, D, S) +VMUL(fmul, 4, F, X, S) +VMUL(fmul, 2, D, X, D) + +// --------------------------------- MLA -------------------------------------- +define(`VMLA', `ifelse($1, fmla, ` +// dst + src1 * src2') +instruct vmla$2$3`'(vec$4 dst, vec$4 src1, vec$4 src2) +%{ifelse($2$3, 4S, ` + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4);', $1, fmla, ` + predicate(UseFMA && n->as_Vector()->length() == $2);', ` + predicate(n->as_Vector()->length() == $2);') + match(Set dst (ifelse($1, mlav, `AddV'$3` dst (MulV$3 src1 src2)', FmaV$3 `dst (Binary src1 src2)'))); + ins_cost(INSN_COST); + format %{ "$1 $dst,$src1,$src2\t# vector ($2$5)" %} + ins_encode %{ + __ $1(as_FloatRegister($dst$$reg), __ T$2`'ifelse($5, L, D, $5), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vm`'ifelse($3, F, uldiv_fp, $3, D, uldiv_fp, la)`'ifelse($4, D, 64, 128)); +%}')dnl +dnl $1 $2 $3 $4 $5 +VMLA(mlav, 4, S, D, H) +VMLA(mlav, 8, S, X, H) +VMLA(mlav, 2, I, D, S) +VMLA(mlav, 4, I, X, S) +VMLA(fmla, 2, F, D, S) +VMLA(fmla, 4, F, X, S) +VMLA(fmla, 2, D, X, D) + +// --------------------------------- MLS -------------------------------------- +define(`VMLS', `ifelse($1, fmls, ` +// dst - src1 * src2') +instruct vmls$2$3`'(vec$4 dst, vec$4 src1, vec$4 src2) %{ifelse($2$3, 4S, ` + predicate(n->as_Vector()->length() == 2 || + n->as_Vector()->length() == 4);', $1, fmls, ` + predicate(UseFMA && n->as_Vector()->length() == $2);', ` + predicate(n->as_Vector()->length() == $2);') + match(Set dst (ifelse($1, mlsv, `SubV'$3` dst (MulV$3 src1 src2)', FmaV$3 `dst (Binary (NegV'$3 `src1) src2))); + match(Set dst (FmaV$3 dst (Binary src1 (NegV'$3 `src2))'))); + ins_cost(INSN_COST); + format %{ "$1 $dst,$src1,$src2\t# vector ($2$5)" %} + ins_encode %{ + __ $1(as_FloatRegister($dst$$reg), __ T$2`'ifelse($5, L, D, $5), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vm`'ifelse($3, F, uldiv_fp, $3, D, uldiv_fp, la)`'ifelse($4, D, 64, 128)); +%}')dnl +dnl $1 $2 $3 $4 $5 +VMLS(mlsv, 4, S, D, H) +VMLS(mlsv, 8, S, X, H) +VMLS(mlsv, 2, I, D, S) +VMLS(mlsv, 4, I, X, S) +VMLS(fmls, 2, F, D, S) +VMLS(fmls, 4, F, X, S) +VMLS(fmls, 2, D, X, D) + +// --------------- Vector Multiply-Add Shorts into Integer -------------------- + +instruct vmuladdS2I(vecX dst, vecX src1, vecX src2, vecX tmp) %{ + predicate(n->in(1)->bottom_type()->is_vect()->element_basic_type() == T_SHORT); + match(Set dst (MulAddVS2VI src1 src2)); + ins_cost(INSN_COST); + effect(TEMP_DEF dst, TEMP tmp); + format %{ "smullv $tmp, $src1, $src2\t# vector (4H)\n\t" + "smullv $dst, $src1, $src2\t# vector (8H)\n\t" + "addpv $dst, $tmp, $dst\t# vector (4S)\n\t" %} + ins_encode %{ + __ smullv(as_FloatRegister($tmp$$reg), __ T4H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + __ smullv(as_FloatRegister($dst$$reg), __ T8H, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + __ addpv(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($tmp$$reg), + as_FloatRegister($dst$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + +// --------------------------------- DIV -------------------------------------- +define(`VDIV', ` +instruct vdiv$2$3`'(vec$4 dst, vec$4 src1, vec$4 src2) +%{ + predicate(n->as_Vector()->length() == $2); + match(Set dst (DivV$3 src1 src2)); + ins_cost(INSN_COST); + format %{ "$1 $dst,$src1,$src2\t# vector ($2$5)" %} + ins_encode %{ + __ $1(as_FloatRegister($dst$$reg), __ T$2`'ifelse($5, L, D, $5), + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp`'ifelse($4, D, 64, 128)); +%}')dnl +dnl $1 $2 $3 $4 $5 +VDIV(fdiv, 2, F, D, S) +VDIV(fdiv, 4, F, X, S) +VDIV(fdiv, 2, D, X, D) + +// --------------------------------- SQRT ------------------------------------- +define(`VSQRT', ` +instruct vsqrt$2$3`'(vec$4 dst, vec$4 src) +%{ + predicate(n->as_Vector()->length() == $2); + match(Set dst (SqrtV$3 src)); + format %{ "$1 $dst, $src\t# vector ($2$3)" %} + ins_encode %{ + __ $1(as_FloatRegister($dst$$reg), __ T$2$5, as_FloatRegister($src$$reg)); + %} + ins_pipe(v`'ifelse($2$3, 2F, unop, sqrt)_fp`'ifelse($4, D, 64, 128)); +%}')dnl +dnl $1 $2 $3 $4 $5 +VSQRT(fsqrt, 2, F, D, S) +VSQRT(fsqrt, 4, F, X, S) +VSQRT(fsqrt, 2, D, X, D) + +// --------------------------------- NEG -------------------------------------- +define(`VNEG', ` +instruct vneg$2$3`'(vec$4 dst, vec$4 src) +%{ + predicate(n->as_Vector()->length() == $2); + match(Set dst (NegV$3 src)); + ins_cost(INSN_COST * 3); + format %{ "$1 $dst,$src\t# vector ($2$5)" %} + ins_encode %{ + __ $1(as_FloatRegister($dst$$reg), __ T$2`'ifelse($5, L, D, $5), + as_FloatRegister($src$$reg)); + %} + ins_pipe(vunop_fp`'ifelse($4, D, 64, 128)); +%}')dnl +dnl $1 $2 $3 $4 $5 +VNEG(fneg, 2, F, D, S) +VNEG(fneg, 4, F, X, S) +VNEG(fneg, 2, D, X, D) +dnl +define(`VLOGICAL', ` +instruct v$3$5$6`'(vec$7 dst, vec$7 src1, vec$7 src2) +%{ + predicate(ifelse($5, 8, n->as_Vector()->length_in_bytes() == 4 ||` + ')n->as_Vector()->length_in_bytes() == $5); + match(Set dst ($4V src1 src2)); + ins_cost(INSN_COST); + format %{ "$1 $dst,$src1,$src2\t# vector ($5$6)" %} + ins_encode %{ + __ $2(as_FloatRegister($dst$$reg), __ T$5$6, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vlogical`'ifelse($7, D, 64, 128)); +%}')dnl + +// --------------------------------- AND -------------------------------------- +dnl $1 $2 $3 $4 $5 $6 $7 +VLOGICAL(and, andr, and, And, 8, B, D) +VLOGICAL(and, andr, and, And, 16, B, X) + +// --------------------------------- OR --------------------------------------- +VLOGICAL(orr, orr, or, Or, 8, B, D) +VLOGICAL(orr, orr, or, Or, 16, B, X) + +// --------------------------------- XOR -------------------------------------- +VLOGICAL(xor, eor, xor, Xor, 8, B, D) +VLOGICAL(xor, eor, xor, Xor, 16, B, X) + +// ------------------------------ Shift --------------------------------------- +dnl +define(`VSHIFTCNT', ` +instruct vshiftcnt$3$4`'(vec$5 dst, iRegIorL2I cnt) %{ + predicate(ifelse($3, 8, n->as_Vector()->length_in_bytes() == 4 ||` + ')n->as_Vector()->length_in_bytes() == $3); + match(Set dst (LShiftCntV cnt)); + match(Set dst (RShiftCntV cnt)); + format %{ "$1 $dst, $cnt\t# shift count vector ($3$4)" %} + ins_encode %{ + __ $2(as_FloatRegister($dst$$reg), __ T$3$4, as_Register($cnt$$reg)); + %} + ins_pipe(vdup_reg_reg`'ifelse($5, D, 64, 128)); +%}')dnl +dnl $1 $2 $3 $4 $5 +VSHIFTCNT(dup, dup, 8, B, D) +VSHIFTCNT(dup, dup, 16, B, X) +dnl +define(`VSLL', ` +instruct vsll$3$4`'(vec$6 dst, vec$6 src, vec$6 shift) %{ + predicate(ifelse($3$4, 8B, n->as_Vector()->length() == 4 ||` + ', + $3$4, 4S, n->as_Vector()->length() == 2 ||` + ')n->as_Vector()->length() == $3); + match(Set dst (LShiftV$4 src shift)); + ins_cost(INSN_COST); + format %{ "$1 $dst,$src,$shift\t# vector ($3$5)" %} + ins_encode %{ + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), + as_FloatRegister($shift$$reg)); + %} + ins_pipe(vshift`'ifelse($6, D, 64, 128)); +%}')dnl +dnl +define(`VSRA', ` +instruct vsra$3$4`'(vec$6 dst, vec$6 src, vec$6 shift, vec$6 tmp) %{ + predicate(ifelse($3$4, 8B, n->as_Vector()->length() == 4 ||` + ', + $3$4, 4S, n->as_Vector()->length() == 2 ||` + ')n->as_Vector()->length() == $3); + match(Set dst (RShiftV$4 src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "$1 $tmp,$shift\t" + "$2 $dst,$src,$tmp\t# vector ($3$5)" %} + ins_encode %{ + __ $1(as_FloatRegister($tmp$$reg), __ T`'ifelse($6, D, 8B, 16B), + as_FloatRegister($shift$$reg)); + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift`'ifelse($6, D, 64, 128)); +%}')dnl +dnl +define(`VSRL', ` +instruct vsrl$3$4`'(vec$6 dst, vec$6 src, vec$6 shift, vec$6 tmp) %{ + predicate(ifelse($3$4, 8B, n->as_Vector()->length() == 4 ||` + ', + $3$4, 4S, n->as_Vector()->length() == 2 ||` + ')n->as_Vector()->length() == $3); + match(Set dst (URShiftV$4 src shift)); + ins_cost(INSN_COST); + effect(TEMP tmp); + format %{ "$1 $tmp,$shift\t" + "$2 $dst,$src,$tmp\t# vector ($3$5)" %} + ins_encode %{ + __ $1(as_FloatRegister($tmp$$reg), __ T`'ifelse($6, D, 8B, 16B), + as_FloatRegister($shift$$reg)); + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), + as_FloatRegister($tmp$$reg)); + %} + ins_pipe(vshift`'ifelse($6, D, 64, 128)); +%}')dnl +dnl +define(`VSLL_IMM', ` +instruct vsll$3$4_imm`'(vec$6 dst, vec$6 src, immI shift) %{ + predicate(ifelse($3$4, 8B, n->as_Vector()->length() == 4 ||` + ', + $3$4, 4S, n->as_Vector()->length() == 2 ||` + ')n->as_Vector()->length() == $3); + match(Set dst (LShiftV$4 src (LShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "$1 $dst, $src, $shift\t# vector ($3$5)" %} + ins_encode %{ifelse($4, B,` + int sh = (int)$shift$$constant; + if (sh >= 8) { + __ eor(as_FloatRegister($dst$$reg), __ ifelse($6, D, T8B, T16B), + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), sh); + }', $4, S,` + int sh = (int)$shift$$constant; + if (sh >= 16) { + __ eor(as_FloatRegister($dst$$reg), __ ifelse($6, D, T8B, T16B), + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), sh); + }', ` + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), + (int)$shift$$constant);') + %} + ins_pipe(vshift`'ifelse($6, D, 64, 128)_imm); +%}')dnl +define(`VSRA_IMM', ` +instruct vsra$3$4_imm`'(vec$6 dst, vec$6 src, immI shift) %{ + predicate(ifelse($3$4, 8B, n->as_Vector()->length() == 4 ||` + ', + $3$4, 4S, n->as_Vector()->length() == 2 ||` + ')n->as_Vector()->length() == $3); + match(Set dst (RShiftV$4 src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "$1 $dst, $src, $shift\t# vector ($3$5)" %} + ins_encode %{ifelse($4, B,` + int sh = (int)$shift$$constant; + if (sh >= 8) sh = 7; + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), sh);', $4, S,` + int sh = (int)$shift$$constant; + if (sh >= 16) sh = 15; + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), sh);', ` + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), + (int)$shift$$constant);') + %} + ins_pipe(vshift`'ifelse($6, D, 64, 128)_imm); +%}')dnl +dnl +define(`VSRL_IMM', ` +instruct vsrl$3$4_imm`'(vec$6 dst, vec$6 src, immI shift) %{ + predicate(ifelse($3$4, 8B, n->as_Vector()->length() == 4 ||` + ', + $3$4, 4S, n->as_Vector()->length() == 2 ||` + ')n->as_Vector()->length() == $3); + match(Set dst (URShiftV$4 src (RShiftCntV shift))); + ins_cost(INSN_COST); + format %{ "$1 $dst, $src, $shift\t# vector ($3$5)" %} + ins_encode %{ifelse($4, B,` + int sh = (int)$shift$$constant; + if (sh >= 8) { + __ eor(as_FloatRegister($dst$$reg), __ ifelse($6, D, T8B, T16B), + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), sh); + }', $4, S,` + int sh = (int)$shift$$constant; + if (sh >= 16) { + __ eor(as_FloatRegister($dst$$reg), __ ifelse($6, D, T8B, T16B), + as_FloatRegister($src$$reg), + as_FloatRegister($src$$reg)); + } else { + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), sh); + }', ` + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), + (int)$shift$$constant);') + %} + ins_pipe(vshift`'ifelse($6, D, 64, 128)_imm); +%}')dnl +dnl +define(`VSRLA_IMM', ` +instruct vsrla$3$4_imm`'(vec$6 dst, vec$6 src, immI shift) %{ + predicate(n->as_Vector()->length() == $3); + match(Set dst (AddV$4 dst (URShiftV$4 src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "$1 $dst, $src, $shift\t# vector ($3$5)" %} + ins_encode %{ifelse($4, B,` + int sh = (int)$shift$$constant; + if (sh < 8) { + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), sh); + }', $4, S,` + int sh = (int)$shift$$constant; + if (sh < 16) { + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), sh); + }', ` + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), + (int)$shift$$constant);') + %} + ins_pipe(vshift`'ifelse($6, D, 64, 128)_imm); +%}')dnl +dnl +define(`VSRAA_IMM', ` +instruct vsraa$3$4_imm`'(vec$6 dst, vec$6 src, immI shift) %{ + predicate(n->as_Vector()->length() == $3); + match(Set dst (AddV$4 dst (RShiftV$4 src (RShiftCntV shift)))); + ins_cost(INSN_COST); + format %{ "$1 $dst, $src, $shift\t# vector ($3$5)" %} + ins_encode %{ifelse($4, B,` + int sh = (int)$shift$$constant; + if (sh >= 8) sh = 7; + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), sh);', $4, S,` + int sh = (int)$shift$$constant; + if (sh >= 16) sh = 15; + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), sh);', ` + __ $2(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src$$reg), + (int)$shift$$constant);') + %} + ins_pipe(vshift`'ifelse($6, D, 64, 128)_imm); +%}')dnl +dnl $1 $2 $3 $4 $5 $6 +VSLL(sshl, sshl, 8, B, B, D) +VSLL(sshl, sshl, 16, B, B, X) + +// Right shifts with vector shift count on aarch64 SIMD are implemented +// as left shift by negative shift count. +// There are two cases for vector shift count. +// +// Case 1: The vector shift count is from replication. +// | | +// LoadVector RShiftCntV +// | / +// RShiftVI +// Note: In inner loop, multiple neg instructions are used, which can be +// moved to outer loop and merge into one neg instruction. +// +// Case 2: The vector shift count is from loading. +// This case isn't supported by middle-end now. But it's supported by +// panama/vectorIntrinsics(JEP 338: Vector API). +// | | +// LoadVector LoadVector +// | / +// RShiftVI +// +dnl $1 $2 $3 $4 $5 $6 +VSRA(negr, sshl, 8, B, B, D) +VSRA(negr, sshl, 16, B, B, X) +VSRL(negr, ushl, 8, B, B, D) +VSRL(negr, ushl, 16, B, B, X) +VSLL_IMM(shl, shl, 8, B, B, D) +VSLL_IMM(shl, shl, 16, B, B, X) +VSRA_IMM(sshr, sshr, 8, B, B, D) +VSRA_IMM(sshr, sshr, 16, B, B, X) +VSRL_IMM(ushr, ushr, 8, B, B, D) +VSRL_IMM(ushr, ushr, 16, B, B, X) +VSLL(sshl, sshl, 4, S, H, D) +VSLL(sshl, sshl, 8, S, H, X) +VSRA(negr, sshl, 4, S, H, D) +VSRA(negr, sshl, 8, S, H, X) +VSRL(negr, ushl, 4, S, H, D) +VSRL(negr, ushl, 8, S, H, X) +VSLL_IMM(shl, shl, 4, S, H, D) +VSLL_IMM(shl, shl, 8, S, H, X) +VSRA_IMM(sshr, sshr, 4, S, H, D) +VSRA_IMM(sshr, sshr, 8, S, H, X) +VSRL_IMM(ushr, ushr, 4, S, H, D) +VSRL_IMM(ushr, ushr, 8, S, H, X) +VSLL(sshl, sshl, 2, I, S, D) +VSLL(sshl, sshl, 4, I, S, X) +VSRA(negr, sshl, 2, I, S, D) +VSRA(negr, sshl, 4, I, S, X) +VSRL(negr, ushl, 2, I, S, D) +VSRL(negr, ushl, 4, I, S, X) +VSLL_IMM(shl, shl, 2, I, S, D) +VSLL_IMM(shl, shl, 4, I, S, X) +VSRA_IMM(sshr, sshr, 2, I, S, D) +VSRA_IMM(sshr, sshr, 4, I, S, X) +VSRL_IMM(ushr, ushr, 2, I, S, D) +VSRL_IMM(ushr, ushr, 4, I, S, X) +VSLL(sshl, sshl, 2, L, D, X) +VSRA(negr, sshl, 2, L, D, X) +VSRL(negr, ushl, 2, L, D, X) +VSLL_IMM(shl, shl, 2, L, D, X) +VSRA_IMM(sshr, sshr, 2, L, D, X) +VSRL_IMM(ushr, ushr, 2, L, D, X) +VSRAA_IMM(ssra, ssra, 8, B, B, D) +VSRAA_IMM(ssra, ssra, 16, B, B, X) +VSRAA_IMM(ssra, ssra, 4, S, H, D) +VSRAA_IMM(ssra, ssra, 8, S, H, X) +VSRAA_IMM(ssra, ssra, 2, I, S, D) +VSRAA_IMM(ssra, ssra, 4, I, S, X) +VSRAA_IMM(ssra, ssra, 2, L, D, X) +VSRLA_IMM(usra, usra, 8, B, B, D) +VSRLA_IMM(usra, usra, 16, B, B, X) +VSRLA_IMM(usra, usra, 4, S, H, D) +VSRLA_IMM(usra, usra, 8, S, H, X) +VSRLA_IMM(usra, usra, 2, I, S, D) +VSRLA_IMM(usra, usra, 4, I, S, X) +VSRLA_IMM(usra, usra, 2, L, D, X) +dnl +define(`VMINMAX', ` +instruct v$1$3`'ifelse($5, S, F, D)`'(vec$6 dst, vec$6 src1, vec$6 src2) +%{ + predicate(n->as_Vector()->length() == $3 && n->bottom_type()->is_vect()->element_basic_type() == T_`'ifelse($5, S, FLOAT, DOUBLE)); + match(Set dst ($2V src1 src2)); + ins_cost(INSN_COST); + format %{ "f$1 $dst,$src1,$src2\t# vector ($3$4)" %} + ins_encode %{ + __ f$1(as_FloatRegister($dst$$reg), __ T$3$5, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vdop_fp`'ifelse($6, D, 64, 128)); +%}')dnl +dnl $1 $2 $3 $4 $5 $6 +VMINMAX(max, Max, 2, F, S, D) +VMINMAX(max, Max, 4, S, S, X) +VMINMAX(max, Max, 2, D, D, X) +VMINMAX(min, Min, 2, F, S, D) +VMINMAX(min, Min, 4, S, S, X) +VMINMAX(min, Min, 2, D, D, X) + +instruct vround2D_reg(vecX dst, vecX src, immI rmode) %{ + predicate(n->as_Vector()->length() == 2 && n->bottom_type()->is_vect()->element_basic_type() == T_DOUBLE); + match(Set dst (RoundDoubleModeV src rmode)); + format %{ "frint $dst, $src, $rmode" %} + ins_encode %{ + switch ($rmode$$constant) { + case RoundDoubleModeNode::rmode_rint: + __ frintn(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg)); + break; + case RoundDoubleModeNode::rmode_floor: + __ frintm(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg)); + break; + case RoundDoubleModeNode::rmode_ceil: + __ frintp(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src$$reg)); + break; + } + %} + ins_pipe(vdop_fp128); +%} +dnl +define(`VPOPCOUNT', ` +instruct vpopcount$1$2`'(vec$5 dst, vec$5 src) %{ + predicate(UsePopCountInstruction && n->as_Vector()->length() == $1); + match(Set dst (PopCountVI src)); + format %{ + "cnt $dst, $src\t# vector ($3B)\n\t" + "uaddlp $dst, $dst\t# vector ($3B)\n\t" + "uaddlp $dst, $dst\t# vector ($4H)" + %} + ins_encode %{ + __ cnt(as_FloatRegister($dst$$reg), __ T$3B, + as_FloatRegister($src$$reg)); + __ uaddlp(as_FloatRegister($dst$$reg), __ T$3B, + as_FloatRegister($dst$$reg)); + __ uaddlp(as_FloatRegister($dst$$reg), __ T$4H, + as_FloatRegister($dst$$reg)); + %} + ins_pipe(pipe_class_default); +%}')dnl +dnl $1 $2 $3 $4 $5 +VPOPCOUNT(4, I, 16, 8, X) +VPOPCOUNT(2, I, 8, 4, D) diff --git a/src/hotspot/cpu/aarch64/atomic_aarch64.hpp b/src/hotspot/cpu/aarch64/atomic_aarch64.hpp new file mode 100644 index 00000000000..dc35fc40cab --- /dev/null +++ b/src/hotspot/cpu/aarch64/atomic_aarch64.hpp @@ -0,0 +1,46 @@ +/* Copyright (c) 2021, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef CPU_AARCH64_ATOMIC_AARCH64_HPP +#define CPU_AARCH64_ATOMIC_AARCH64_HPP + +// Atomic stub implementation. +// Default implementations are in atomic_linux_aarch64.S +// +// All stubs pass arguments the same way +// x0: src/dest address +// x1: arg1 +// x2: arg2 (optional) +// x3, x8, x9: scratch +typedef uint64_t (*aarch64_atomic_stub_t)(volatile void *ptr, uint64_t arg1, uint64_t arg2); + +// Pointers to stubs +extern aarch64_atomic_stub_t aarch64_atomic_fetch_add_4_impl; +extern aarch64_atomic_stub_t aarch64_atomic_fetch_add_8_impl; +extern aarch64_atomic_stub_t aarch64_atomic_xchg_4_impl; +extern aarch64_atomic_stub_t aarch64_atomic_xchg_8_impl; +extern aarch64_atomic_stub_t aarch64_atomic_cmpxchg_1_impl; +extern aarch64_atomic_stub_t aarch64_atomic_cmpxchg_4_impl; +extern aarch64_atomic_stub_t aarch64_atomic_cmpxchg_8_impl; + +#endif // CPU_AARCH64_ATOMIC_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp index 681ebd8fe15..bd2a442dcbd 100644 --- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp @@ -32,6 +32,7 @@ #include "compiler/disassembler.hpp" #include "gc/shared/cardTable.hpp" #include "gc/shared/cardTableBarrierSet.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/tlab_globals.hpp" #include "interpreter/interpreter.hpp" #include "memory/universe.hpp" diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp index 9460162198e..41f2591e714 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -600,7 +600,7 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) oop* obj_p = (oop*)tos_addr; obj = (obj_p == NULL) ? (oop)NULL : *obj_p; } - assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check"); + assert(Universe::is_in_heap_or_null(obj), "sanity check"); *oop_result = obj; break; } diff --git a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp index e1eb9fcc2eb..22a2034ff19 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/classLoaderData.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" #include "gc/shared/barrierSetNMethod.hpp" diff --git a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp index 3533f21ac3a..2b5a31b405f 100644 --- a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp @@ -38,9 +38,6 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register ob BarrierSet* bs = BarrierSet::barrier_set(); assert(bs->kind() == BarrierSet::CardTableBarrierSet, "Wrong barrier set kind"); - CardTableBarrierSet* ctbs = barrier_set_cast(bs); - CardTable* ct = ctbs->card_table(); - __ lsr(obj, obj, CardTable::card_shift); assert(CardTable::dirty_card_val() == 0, "must be"); @@ -55,19 +52,12 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register ob __ strb(zr, Address(obj, rscratch1)); __ bind(L_already_dirty); } else { - if (ct->scanned_concurrently()) { - __ membar(Assembler::StoreStore); - } __ strb(zr, Address(obj, rscratch1)); } } void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register start, Register count, Register scratch, RegSet saved_regs) { - BarrierSet* bs = BarrierSet::barrier_set(); - CardTableBarrierSet* ctbs = barrier_set_cast(bs); - CardTable* ct = ctbs->card_table(); - Label L_loop, L_done; const Register end = count; @@ -81,9 +71,6 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl __ load_byte_map_base(scratch); __ add(start, start, scratch); - if (ct->scanned_concurrently()) { - __ membar(__ StoreStore); - } __ bind(L_loop); __ strb(zr, Address(start, count)); __ subs(count, count, 1); diff --git a/src/hotspot/cpu/aarch64/interpreterRT_aarch64.cpp b/src/hotspot/cpu/aarch64/interpreterRT_aarch64.cpp index cc22c477172..19ce88b91b0 100644 --- a/src/hotspot/cpu/aarch64/interpreterRT_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interpreterRT_aarch64.cpp @@ -43,215 +43,103 @@ Register InterpreterRuntime::SignatureHandlerGenerator::from() { return rlocals; Register InterpreterRuntime::SignatureHandlerGenerator::to() { return sp; } Register InterpreterRuntime::SignatureHandlerGenerator::temp() { return rscratch1; } +Register InterpreterRuntime::SignatureHandlerGenerator::next_gpr() { + if (_num_reg_int_args < Argument::n_int_register_parameters_c-1) { + return as_Register(_num_reg_int_args++ + c_rarg1->encoding()); + } + return noreg; +} + +FloatRegister InterpreterRuntime::SignatureHandlerGenerator::next_fpr() { + if (_num_reg_fp_args < Argument::n_float_register_parameters_c) { + return as_FloatRegister(_num_reg_fp_args++); + } + return fnoreg; +} + +int InterpreterRuntime::SignatureHandlerGenerator::next_stack_offset() { + int ret = _stack_offset; + _stack_offset += wordSize; + return ret; +} + InterpreterRuntime::SignatureHandlerGenerator::SignatureHandlerGenerator( const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) { _masm = new MacroAssembler(buffer); - _num_int_args = (method->is_static() ? 1 : 0); - _num_fp_args = 0; + _num_reg_int_args = (method->is_static() ? 1 : 0); + _num_reg_fp_args = 0; _stack_offset = 0; } void InterpreterRuntime::SignatureHandlerGenerator::pass_int() { const Address src(from(), Interpreter::local_offset_in_bytes(offset())); - switch (_num_int_args) { - case 0: - __ ldr(c_rarg1, src); - _num_int_args++; - break; - case 1: - __ ldr(c_rarg2, src); - _num_int_args++; - break; - case 2: - __ ldr(c_rarg3, src); - _num_int_args++; - break; - case 3: - __ ldr(c_rarg4, src); - _num_int_args++; - break; - case 4: - __ ldr(c_rarg5, src); - _num_int_args++; - break; - case 5: - __ ldr(c_rarg6, src); - _num_int_args++; - break; - case 6: - __ ldr(c_rarg7, src); - _num_int_args++; - break; - default: - __ ldr(r0, src); - __ str(r0, Address(to(), _stack_offset)); - _stack_offset += wordSize; - _num_int_args++; - break; + Register reg = next_gpr(); + if (reg != noreg) { + __ ldr(reg, src); + } else { + __ ldrw(r0, src); + __ strw(r0, Address(to(), next_stack_offset())); } } void InterpreterRuntime::SignatureHandlerGenerator::pass_long() { const Address src(from(), Interpreter::local_offset_in_bytes(offset() + 1)); - switch (_num_int_args) { - case 0: - __ ldr(c_rarg1, src); - _num_int_args++; - break; - case 1: - __ ldr(c_rarg2, src); - _num_int_args++; - break; - case 2: - __ ldr(c_rarg3, src); - _num_int_args++; - break; - case 3: - __ ldr(c_rarg4, src); - _num_int_args++; - break; - case 4: - __ ldr(c_rarg5, src); - _num_int_args++; - break; - case 5: - __ ldr(c_rarg6, src); - _num_int_args++; - break; - case 6: - __ ldr(c_rarg7, src); - _num_int_args++; - break; - default: + Register reg = next_gpr(); + if (reg != noreg) { + __ ldr(reg, src); + } else { __ ldr(r0, src); - __ str(r0, Address(to(), _stack_offset)); - _stack_offset += wordSize; - _num_int_args++; - break; + __ str(r0, Address(to(), next_stack_offset())); } } void InterpreterRuntime::SignatureHandlerGenerator::pass_float() { const Address src(from(), Interpreter::local_offset_in_bytes(offset())); - if (_num_fp_args < Argument::n_float_register_parameters_c) { - __ ldrs(as_FloatRegister(_num_fp_args++), src); + FloatRegister reg = next_fpr(); + if (reg != fnoreg) { + __ ldrs(reg, src); } else { __ ldrw(r0, src); - __ strw(r0, Address(to(), _stack_offset)); - _stack_offset += wordSize; - _num_fp_args++; + __ strw(r0, Address(to(), next_stack_offset())); } } void InterpreterRuntime::SignatureHandlerGenerator::pass_double() { const Address src(from(), Interpreter::local_offset_in_bytes(offset() + 1)); - if (_num_fp_args < Argument::n_float_register_parameters_c) { - __ ldrd(as_FloatRegister(_num_fp_args++), src); + FloatRegister reg = next_fpr(); + if (reg != fnoreg) { + __ ldrd(reg, src); } else { __ ldr(r0, src); - __ str(r0, Address(to(), _stack_offset)); - _stack_offset += wordSize; - _num_fp_args++; + __ str(r0, Address(to(), next_stack_offset())); } } void InterpreterRuntime::SignatureHandlerGenerator::pass_object() { - - switch (_num_int_args) { - case 0: + Register reg = next_gpr(); + if (reg == c_rarg1) { assert(offset() == 0, "argument register 1 can only be (non-null) receiver"); __ add(c_rarg1, from(), Interpreter::local_offset_in_bytes(offset())); - _num_int_args++; - break; - case 1: - { - __ add(r0, from(), Interpreter::local_offset_in_bytes(offset())); - __ mov(c_rarg2, 0); - __ ldr(temp(), r0); - Label L; - __ cbz(temp(), L); - __ mov(c_rarg2, r0); - __ bind(L); - _num_int_args++; - break; - } - case 2: - { - __ add(r0, from(), Interpreter::local_offset_in_bytes(offset())); - __ mov(c_rarg3, 0); - __ ldr(temp(), r0); - Label L; - __ cbz(temp(), L); - __ mov(c_rarg3, r0); - __ bind(L); - _num_int_args++; - break; - } - case 3: - { - __ add(r0, from(), Interpreter::local_offset_in_bytes(offset())); - __ mov(c_rarg4, 0); - __ ldr(temp(), r0); - Label L; - __ cbz(temp(), L); - __ mov(c_rarg4, r0); - __ bind(L); - _num_int_args++; - break; - } - case 4: - { - __ add(r0, from(), Interpreter::local_offset_in_bytes(offset())); - __ mov(c_rarg5, 0); - __ ldr(temp(), r0); - Label L; - __ cbz(temp(), L); - __ mov(c_rarg5, r0); - __ bind(L); - _num_int_args++; - break; - } - case 5: - { - __ add(r0, from(), Interpreter::local_offset_in_bytes(offset())); - __ mov(c_rarg6, 0); - __ ldr(temp(), r0); - Label L; - __ cbz(temp(), L); - __ mov(c_rarg6, r0); - __ bind(L); - _num_int_args++; - break; - } - case 6: - { - __ add(r0, from(), Interpreter::local_offset_in_bytes(offset())); - __ mov(c_rarg7, 0); - __ ldr(temp(), r0); - Label L; - __ cbz(temp(), L); - __ mov(c_rarg7, r0); - __ bind(L); - _num_int_args++; - break; - } - default: - { - __ add(r0, from(), Interpreter::local_offset_in_bytes(offset())); - __ ldr(temp(), r0); - Label L; - __ cbnz(temp(), L); - __ mov(r0, zr); - __ bind(L); - __ str(r0, Address(to(), _stack_offset)); - _stack_offset += wordSize; - _num_int_args++; - break; - } + } else if (reg != noreg) { + __ add(r0, from(), Interpreter::local_offset_in_bytes(offset())); + __ mov(reg, 0); + __ ldr(temp(), r0); + Label L; + __ cbz(temp(), L); + __ mov(reg, r0); + __ bind(L); + } else { + __ add(r0, from(), Interpreter::local_offset_in_bytes(offset())); + __ ldr(temp(), r0); + Label L; + __ cbnz(temp(), L); + __ mov(r0, zr); + __ bind(L); + __ str(r0, Address(to(), next_stack_offset())); } } @@ -284,48 +172,45 @@ class SlowSignatureHandler intptr_t* _int_args; intptr_t* _fp_args; intptr_t* _fp_identifiers; - unsigned int _num_int_args; - unsigned int _num_fp_args; + unsigned int _num_reg_int_args; + unsigned int _num_reg_fp_args; - virtual void pass_int() - { - jint from_obj = *(jint *)(_from+Interpreter::local_offset_in_bytes(0)); + intptr_t* single_slot_addr() { + intptr_t* from_addr = (intptr_t*)(_from+Interpreter::local_offset_in_bytes(0)); _from -= Interpreter::stackElementSize; - - if (_num_int_args < Argument::n_int_register_parameters_c-1) { - *_int_args++ = from_obj; - _num_int_args++; - } else { - *_to++ = from_obj; - _num_int_args++; - } + return from_addr; } - virtual void pass_long() - { - intptr_t from_obj = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(1)); + intptr_t* double_slot_addr() { + intptr_t* from_addr = (intptr_t*)(_from+Interpreter::local_offset_in_bytes(1)); _from -= 2*Interpreter::stackElementSize; + return from_addr; + } - if (_num_int_args < Argument::n_int_register_parameters_c-1) { - *_int_args++ = from_obj; - _num_int_args++; - } else { - *_to++ = from_obj; - _num_int_args++; + int pass_gpr(intptr_t value) { + if (_num_reg_int_args < Argument::n_int_register_parameters_c-1) { + *_int_args++ = value; + return _num_reg_int_args++; } + return -1; } - virtual void pass_object() - { - intptr_t *from_addr = (intptr_t*)(_from + Interpreter::local_offset_in_bytes(0)); - _from -= Interpreter::stackElementSize; + int pass_fpr(intptr_t value) { + if (_num_reg_fp_args < Argument::n_float_register_parameters_c) { + *_fp_args++ = value; + return _num_reg_fp_args++; + } + return -1; + } - if (_num_int_args < Argument::n_int_register_parameters_c-1) { - *_int_args++ = (*from_addr == 0) ? NULL : (intptr_t)from_addr; - _num_int_args++; - } else { - *_to++ = (*from_addr == 0) ? NULL : (intptr_t) from_addr; - _num_int_args++; + void pass_stack(intptr_t value) { + *_to++ = value; + } + + virtual void pass_int() { + jint value = *(jint*)single_slot_addr(); + if (pass_gpr(value) < 0) { + pass_stack(value); } } @@ -334,32 +219,35 @@ class SlowSignatureHandler pass_object(); } - virtual void pass_float() - { - jint from_obj = *(jint*)(_from+Interpreter::local_offset_in_bytes(0)); - _from -= Interpreter::stackElementSize; + virtual void pass_long() { + intptr_t value = *double_slot_addr(); + if (pass_gpr(value) < 0) { + pass_stack(value); + } + } - if (_num_fp_args < Argument::n_float_register_parameters_c) { - *_fp_args++ = from_obj; - _num_fp_args++; - } else { - *_to++ = from_obj; - _num_fp_args++; + virtual void pass_object() { + intptr_t* addr = single_slot_addr(); + intptr_t value = *addr == 0 ? NULL : (intptr_t)addr; + if (pass_gpr(value) < 0) { + pass_stack(value); } } - virtual void pass_double() - { - intptr_t from_obj = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(1)); - _from -= 2*Interpreter::stackElementSize; + virtual void pass_float() { + jint value = *(jint*)single_slot_addr(); + if (pass_fpr(value) < 0) { + pass_stack(value); + } + } - if (_num_fp_args < Argument::n_float_register_parameters_c) { - *_fp_args++ = from_obj; - *_fp_identifiers |= (1ull << _num_fp_args); // mark as double - _num_fp_args++; + virtual void pass_double() { + intptr_t value = *double_slot_addr(); + int arg = pass_fpr(value); + if (0 <= arg) { + *_fp_identifiers |= (1ull << arg); // mark as double } else { - *_to++ = from_obj; - _num_fp_args++; + pass_stack(value); } } @@ -374,8 +262,8 @@ class SlowSignatureHandler _fp_args = to - 8; _fp_identifiers = to - 9; *(int*) _fp_identifiers = 0; - _num_int_args = (method->is_static() ? 1 : 0); - _num_fp_args = 0; + _num_reg_int_args = (method->is_static() ? 1 : 0); + _num_reg_fp_args = 0; } }; diff --git a/src/hotspot/cpu/aarch64/interpreterRT_aarch64.hpp b/src/hotspot/cpu/aarch64/interpreterRT_aarch64.hpp index 792943cf624..13c589e469c 100644 --- a/src/hotspot/cpu/aarch64/interpreterRT_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/interpreterRT_aarch64.hpp @@ -34,8 +34,8 @@ class SignatureHandlerGenerator: public NativeSignatureIterator { private: MacroAssembler* _masm; - unsigned int _num_fp_args; - unsigned int _num_int_args; + unsigned int _num_reg_fp_args; + unsigned int _num_reg_int_args; int _stack_offset; void pass_int(); @@ -45,6 +45,10 @@ class SignatureHandlerGenerator: public NativeSignatureIterator { void pass_object(); void pass_valuetype(); + Register next_gpr(); + FloatRegister next_fpr(); + int next_stack_offset(); + public: // Creation SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer); diff --git a/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp b/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp index cbe58e692dc..17b9780129d 100644 --- a/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp @@ -30,6 +30,7 @@ #include "jvmci/jvmciJavaClasses.hpp" #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/sharedRuntime.hpp" #include "vmreg_aarch64.inline.hpp" diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 10625ae642a..a180da3a6cd 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -30,9 +30,10 @@ #include "asm/assembler.hpp" #include "asm/assembler.inline.hpp" #include "gc/shared/barrierSet.hpp" -#include "gc/shared/cardTable.hpp" #include "gc/shared/barrierSetAssembler.hpp" #include "gc/shared/cardTableBarrierSet.hpp" +#include "gc/shared/cardTable.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/tlab_globals.hpp" #include "interpreter/interpreter.hpp" #include "compiler/disassembler.hpp" @@ -2612,6 +2613,8 @@ void MacroAssembler::atomic_##OP(Register prev, Register newv, Register addr) { ATOMIC_XCHG(xchg, swp, ldxr, stxr, Assembler::xword) ATOMIC_XCHG(xchgw, swp, ldxrw, stxrw, Assembler::word) +ATOMIC_XCHG(xchgl, swpl, ldxr, stlxr, Assembler::xword) +ATOMIC_XCHG(xchglw, swpl, ldxrw, stlxrw, Assembler::word) ATOMIC_XCHG(xchgal, swpal, ldaxr, stlxr, Assembler::xword) ATOMIC_XCHG(xchgalw, swpal, ldaxrw, stlxrw, Assembler::word) @@ -5330,10 +5333,14 @@ void MacroAssembler::char_array_compress(Register src, Register dst, Register le // by the call to JavaThread::aarch64_get_thread_helper() or, indeed, // the call setup code. // -// aarch64_get_thread_helper() clobbers only r0, r1, and flags. +// On Linux, aarch64_get_thread_helper() clobbers only r0, r1, and flags. +// On other systems, the helper is a usual C function. // void MacroAssembler::get_thread(Register dst) { - RegSet saved_regs = RegSet::range(r0, r1) + lr - dst; + RegSet saved_regs = + LINUX_ONLY(RegSet::range(r0, r1) + lr - dst) + NOT_LINUX (RegSet::range(r0, r17) + lr - dst); + push(saved_regs, sp); mov(lr, CAST_FROM_FN_PTR(address, JavaThread::aarch64_get_thread_helper)); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index 9b4a95b1e1e..7dbdd49144f 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -1057,6 +1057,8 @@ class MacroAssembler: public Assembler { void atomic_xchg(Register prev, Register newv, Register addr); void atomic_xchgw(Register prev, Register newv, Register addr); + void atomic_xchgl(Register prev, Register newv, Register addr); + void atomic_xchglw(Register prev, Register newv, Register addr); void atomic_xchgal(Register prev, Register newv, Register addr); void atomic_xchgalw(Register prev, Register newv, Register addr); diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp index 898f098d8cb..734963145c5 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -27,6 +27,7 @@ #include "asm/macroAssembler.hpp" #include "code/codeCache.hpp" #include "code/compiledIC.hpp" +#include "gc/shared/collectedHeap.hpp" #include "memory/resourceArea.hpp" #include "nativeInst_aarch64.hpp" #include "oops/oop.inline.hpp" diff --git a/src/hotspot/cpu/aarch64/registerMap_aarch64.cpp b/src/hotspot/cpu/aarch64/registerMap_aarch64.cpp new file mode 100644 index 00000000000..18e55fa0348 --- /dev/null +++ b/src/hotspot/cpu/aarch64/registerMap_aarch64.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Arm Limited. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "runtime/registerMap.hpp" +#include "vmreg_aarch64.inline.hpp" + +address RegisterMap::pd_location(VMReg base_reg, int slot_idx) const { + if (base_reg->is_FloatRegister()) { + // Not all physical slots of an SVE register have corresponding + // VMRegs. However they are always saved to the stack in a + // contiguous region of memory so we can calculate the address of + // the upper slots by offsetting from the base address. + assert(base_reg->is_concrete(), "must pass base reg"); + int base_reg_enc = (base_reg->value() - ConcreteRegisterImpl::max_gpr) / + FloatRegisterImpl::max_slots_per_register; + intptr_t offset_in_bytes = slot_idx * VMRegImpl::stack_slot_size; + address base_location = location(base_reg); + if (base_location != NULL) { + return base_location + offset_in_bytes; + } else { + return NULL; + } + } else { + return location(base_reg->next(slot_idx)); + } +} diff --git a/src/hotspot/cpu/aarch64/registerMap_aarch64.hpp b/src/hotspot/cpu/aarch64/registerMap_aarch64.hpp index 9283521bf1b..1f84b4d2d3e 100644 --- a/src/hotspot/cpu/aarch64/registerMap_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/registerMap_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -32,8 +32,8 @@ private: // This is the hook for finding a register in an "well-known" location, // such as a register block of a predetermined format. - // Since there is none, we just return NULL. - address pd_location(VMReg reg) const {return NULL;} + address pd_location(VMReg reg) const { return NULL; } + address pd_location(VMReg base_reg, int slot_idx) const; // no PD state to clear or copy: void pd_clear() {} diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index dc57d4c4c47..a4b42b72830 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -40,12 +40,14 @@ #include "oops/compiledICHolder.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/safepointMechanism.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/vframeArray.hpp" #include "utilities/align.hpp" +#include "utilities/formatBuffer.hpp" #include "vmreg_aarch64.inline.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" @@ -84,26 +86,24 @@ class SimpleRuntimeFrame { // FIXME -- this is used by C1 class RegisterSaver { + const bool _save_vectors; public: - static OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors = false); - static void restore_live_registers(MacroAssembler* masm, bool restore_vectors = false); + RegisterSaver(bool save_vectors) : _save_vectors(save_vectors) {} + + OopMap* save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words); + void restore_live_registers(MacroAssembler* masm); // Offsets into the register save area // Used by deoptimization when it is managing result register // values on its own - static int r0_offset_in_bytes(void) { return (32 + r0->encoding()) * wordSize; } - static int reg_offset_in_bytes(Register r) { return r0_offset_in_bytes() + r->encoding() * wordSize; } - static int rmethod_offset_in_bytes(void) { return reg_offset_in_bytes(rmethod); } - static int rscratch1_offset_in_bytes(void) { return (32 + rscratch1->encoding()) * wordSize; } - static int v0_offset_in_bytes(void) { return 0; } - static int return_offset_in_bytes(void) { return (32 /* floats*/ + 31 /* gregs*/) * wordSize; } - - // During deoptimization only the result registers need to be restored, - // all the other values have already been extracted. - static void restore_result_registers(MacroAssembler* masm); + int reg_offset_in_bytes(Register r); + int r0_offset_in_bytes() { return reg_offset_in_bytes(r0); } + int rscratch1_offset_in_bytes() { return reg_offset_in_bytes(rscratch1); } + int v0_offset_in_bytes(void) { return 0; } - // Capture info about frame layout + // Capture info about frame layout + // Note this is only correct when not saving full vectors. enum layout { fpu_state_off = 0, fpu_state_end = fpu_state_off + FPUStateSizeInWords - 1, @@ -118,7 +118,31 @@ class RegisterSaver { }; -OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words, bool save_vectors) { +int RegisterSaver::reg_offset_in_bytes(Register r) { + // The integer registers are located above the floating point + // registers in the stack frame pushed by save_live_registers() so the + // offset depends on whether we are saving full vectors, and whether + // those vectors are NEON or SVE. + + int slots_per_vect = FloatRegisterImpl::save_slots_per_register; + +#if COMPILER2_OR_JVMCI + if (_save_vectors) { + slots_per_vect = FloatRegisterImpl::slots_per_neon_register; + +#ifdef COMPILER2 + if (Matcher::supports_scalable_vector()) { + slots_per_vect = Matcher::scalable_vector_reg_size(T_FLOAT); + } +#endif + } +#endif + + int r0_offset = (slots_per_vect * FloatRegisterImpl::number_of_registers) * BytesPerInt; + return r0_offset + r->encoding() * wordSize; +} + +OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_frame_words, int* total_frame_words) { bool use_sve = false; int sve_vector_size_in_bytes = 0; int sve_vector_size_in_slots = 0; @@ -130,7 +154,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ #endif #if COMPILER2_OR_JVMCI - if (save_vectors) { + if (_save_vectors) { int vect_words = 0; int extra_save_slots_per_register = 0; // Save upper half of vector registers @@ -144,7 +168,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ additional_frame_words += vect_words; } #else - assert(!save_vectors, "vectors are generated only by C2 and JVMCI"); + assert(!_save_vectors, "vectors are generated only by C2 and JVMCI"); #endif int frame_size_in_bytes = align_up(additional_frame_words * wordSize + @@ -159,7 +183,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ // Save Integer and Float registers. __ enter(); - __ push_CPU_state(save_vectors, use_sve, sve_vector_size_in_bytes); + __ push_CPU_state(_save_vectors, use_sve, sve_vector_size_in_bytes); // Set an oopmap for the call site. This oopmap will map all // oop-registers and debug-info registers as callee-saved. This @@ -184,7 +208,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ for (int i = 0; i < FloatRegisterImpl::number_of_registers; i++) { FloatRegister r = as_FloatRegister(i); int sp_offset = 0; - if (save_vectors) { + if (_save_vectors) { sp_offset = use_sve ? (sve_vector_size_in_slots * i) : (FloatRegisterImpl::slots_per_neon_register * i); } else { @@ -197,37 +221,20 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ return oop_map; } -void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) { +void RegisterSaver::restore_live_registers(MacroAssembler* masm) { #ifdef COMPILER2 - __ pop_CPU_state(restore_vectors, Matcher::supports_scalable_vector(), + __ pop_CPU_state(_save_vectors, Matcher::supports_scalable_vector(), Matcher::scalable_vector_reg_size(T_BYTE)); #else #if !INCLUDE_JVMCI - assert(!restore_vectors, "vectors are generated only by C2 and JVMCI"); + assert(!_save_vectors, "vectors are generated only by C2 and JVMCI"); #endif - __ pop_CPU_state(restore_vectors); + __ pop_CPU_state(_save_vectors); #endif __ leave(); } -void RegisterSaver::restore_result_registers(MacroAssembler* masm) { - - // Just restore result register. Only used by deoptimization. By - // now any callee save register that needs to be restored to a c2 - // caller of the deoptee has been extracted into the vframeArray - // and will be stuffed into the c2i adapter we create for later - // restoration so only result registers need to be restored here. - - // Restore fp result register - __ ldrd(v0, Address(sp, v0_offset_in_bytes())); - // Restore integer result register - __ ldr(r0, Address(sp, r0_offset_in_bytes())); - - // Pop all of the register save are off the stack - __ add(sp, sp, align_up(return_offset_in_bytes(), 16)); -} - // Is vector's size (in bytes) bigger than a size saved by default? // 8 bytes vector registers are saved by default on AArch64. bool SharedRuntime::is_wide_vector(int size) { @@ -2431,6 +2438,7 @@ void SharedRuntime::generate_deopt_blob() { int frame_size_in_words; OopMap* map = NULL; OopMapSet *oop_maps = new OopMapSet(); + RegisterSaver reg_save(COMPILER2_OR_JVMCI != 0); // ------------- // This code enters when returning to a de-optimized nmethod. A return @@ -2468,7 +2476,7 @@ void SharedRuntime::generate_deopt_blob() { // Prolog for non exception case! // Save everything in sight. - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + map = reg_save.save_live_registers(masm, 0, &frame_size_in_words); // Normal deoptimization. Save exec mode for unpack_frames. __ movw(rcpool, Deoptimization::Unpack_deopt); // callee-saved @@ -2486,7 +2494,7 @@ void SharedRuntime::generate_deopt_blob() { // return address is the pc describes what bci to do re-execute at // No need to update map as each call to save_live_registers will produce identical oopmap - (void) RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + (void) reg_save.save_live_registers(masm, 0, &frame_size_in_words); __ movw(rcpool, Deoptimization::Unpack_reexecute); // callee-saved __ b(cont); @@ -2505,7 +2513,7 @@ void SharedRuntime::generate_deopt_blob() { uncommon_trap_offset = __ pc() - start; // Save everything in sight. - RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + reg_save.save_live_registers(masm, 0, &frame_size_in_words); // fetch_unroll_info needs to call last_java_frame() Label retaddr; __ set_last_Java_frame(sp, noreg, retaddr, rscratch1); @@ -2562,7 +2570,7 @@ void SharedRuntime::generate_deopt_blob() { // This is a somewhat fragile mechanism. // Save everything in sight. - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + map = reg_save.save_live_registers(masm, 0, &frame_size_in_words); // Now it is safe to overwrite any register @@ -2643,7 +2651,7 @@ void SharedRuntime::generate_deopt_blob() { __ verify_oop(r0); // Overwrite the result registers with the exception results. - __ str(r0, Address(sp, RegisterSaver::r0_offset_in_bytes())); + __ str(r0, Address(sp, reg_save.r0_offset_in_bytes())); // I think this is useless // __ str(r3, Address(sp, RegisterSaver::r3_offset_in_bytes())); @@ -2652,7 +2660,14 @@ void SharedRuntime::generate_deopt_blob() { // Only register save data is on the stack. // Now restore the result registers. Everything else is either dead // or captured in the vframeArray. - RegisterSaver::restore_result_registers(masm); + + // Restore fp result register + __ ldrd(v0, Address(sp, reg_save.v0_offset_in_bytes())); + // Restore integer result register + __ ldr(r0, Address(sp, reg_save.r0_offset_in_bytes())); + + // Pop all of the register save area off the stack + __ add(sp, sp, frame_size_in_words * wordSize); // All of the register save area has been popped of the stack. Only the // return address remains. @@ -2733,8 +2748,8 @@ void SharedRuntime::generate_deopt_blob() { __ sub(sp, sp, (frame_size_in_words - 2) * wordSize); // Restore frame locals after moving the frame - __ strd(v0, Address(sp, RegisterSaver::v0_offset_in_bytes())); - __ str(r0, Address(sp, RegisterSaver::r0_offset_in_bytes())); + __ strd(v0, Address(sp, reg_save.v0_offset_in_bytes())); + __ str(r0, Address(sp, reg_save.r0_offset_in_bytes())); // Call C code. Need thread but NOT official VM entry // crud. We cannot block on this call, no GC can happen. Call should @@ -2761,8 +2776,8 @@ void SharedRuntime::generate_deopt_blob() { __ reset_last_Java_frame(true); // Collect return values - __ ldrd(v0, Address(sp, RegisterSaver::v0_offset_in_bytes())); - __ ldr(r0, Address(sp, RegisterSaver::r0_offset_in_bytes())); + __ ldrd(v0, Address(sp, reg_save.v0_offset_in_bytes())); + __ ldr(r0, Address(sp, reg_save.r0_offset_in_bytes())); // I think this is useless (throwing pc?) // __ ldr(r3, Address(sp, RegisterSaver::r3_offset_in_bytes())); @@ -3008,10 +3023,10 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t address call_pc = NULL; int frame_size_in_words; bool cause_return = (poll_type == POLL_AT_RETURN); - bool save_vectors = (poll_type == POLL_AT_VECTOR_LOOP); + RegisterSaver reg_save(poll_type == POLL_AT_VECTOR_LOOP /* save_vectors */); // Save Integer and Float registers. - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words, save_vectors); + map = reg_save.save_live_registers(masm, 0, &frame_size_in_words); // The following is basically a call_VM. However, we need the precise // address of the call in order to generate an oopmap. Hence, we do all the @@ -3056,7 +3071,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t // Exception pending - RegisterSaver::restore_live_registers(masm, save_vectors); + reg_save.restore_live_registers(masm); __ far_jump(RuntimeAddress(StubRoutines::forward_exception_entry())); @@ -3088,7 +3103,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t __ bind(no_adjust); // Normal exit, restore registers and exit. - RegisterSaver::restore_live_registers(masm, save_vectors); + reg_save.restore_live_registers(masm); __ ret(lr); @@ -3122,13 +3137,14 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha MacroAssembler* masm = new MacroAssembler(&buffer); int frame_size_in_words; + RegisterSaver reg_save(false /* save_vectors */); OopMapSet *oop_maps = new OopMapSet(); OopMap* map = NULL; int start = __ offset(); - map = RegisterSaver::save_live_registers(masm, 0, &frame_size_in_words); + map = reg_save.save_live_registers(masm, 0, &frame_size_in_words); int frame_complete = __ offset(); @@ -3160,11 +3176,11 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha // get the returned Method* __ get_vm_result_2(rmethod, rthread); - __ str(rmethod, Address(sp, RegisterSaver::reg_offset_in_bytes(rmethod))); + __ str(rmethod, Address(sp, reg_save.reg_offset_in_bytes(rmethod))); // r0 is where we want to jump, overwrite rscratch1 which is saved and scratch - __ str(r0, Address(sp, RegisterSaver::rscratch1_offset_in_bytes())); - RegisterSaver::restore_live_registers(masm); + __ str(r0, Address(sp, reg_save.rscratch1_offset_in_bytes())); + reg_save.restore_live_registers(masm); // We are back the the original state on entry and ready to go. @@ -3174,7 +3190,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha __ bind(pending); - RegisterSaver::restore_live_registers(masm); + reg_save.restore_live_registers(masm); // exception pending => remove activation and forward to exception handler diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index 5d1ef8f4639..99676d2efd9 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -26,6 +26,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" +#include "atomic_aarch64.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" #include "gc/shared/gc_globals.hpp" @@ -38,6 +39,7 @@ #include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "prims/methodHandles.hpp" +#include "runtime/atomic.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/sharedRuntime.hpp" @@ -1376,7 +1378,7 @@ class StubGenerator: public StubCodeGenerator { // // If 'from' and/or 'to' are aligned on 4-byte boundaries, we let // the hardware handle it. The two dwords within qwords that span - // cache line boundaries will still be loaded and stored atomicly. + // cache line boundaries will still be loaded and stored atomically. // // Side Effects: // disjoint_int_copy_entry is set to the no-overlap entry point @@ -1446,7 +1448,7 @@ class StubGenerator: public StubCodeGenerator { // // If 'from' and/or 'to' are aligned on 4-byte boundaries, we let // the hardware handle it. The two dwords within qwords that span - // cache line boundaries will still be loaded and stored atomicly. + // cache line boundaries will still be loaded and stored atomically. // address generate_conjoint_copy(int size, bool aligned, bool is_oop, address nooverlap_target, address *entry, const char *name, @@ -1611,7 +1613,7 @@ class StubGenerator: public StubCodeGenerator { // // If 'from' and/or 'to' are aligned on 4-byte boundaries, we let // the hardware handle it. The two dwords within qwords that span - // cache line boundaries will still be loaded and stored atomicly. + // cache line boundaries will still be loaded and stored atomically. // // Side Effects: // disjoint_int_copy_entry is set to the no-overlap entry point @@ -1635,7 +1637,7 @@ class StubGenerator: public StubCodeGenerator { // // If 'from' and/or 'to' are aligned on 4-byte boundaries, we let // the hardware handle it. The two dwords within qwords that span - // cache line boundaries will still be loaded and stored atomicly. + // cache line boundaries will still be loaded and stored atomically. // address generate_conjoint_int_copy(bool aligned, address nooverlap_target, address *entry, const char *name, @@ -5586,6 +5588,91 @@ class StubGenerator: public StubCodeGenerator { return start; } +#ifdef LINUX + // ARMv8.1 LSE versions of the atomic stubs used by Atomic::PlatformXX. + // + // If LSE is in use, generate LSE versions of all the stubs. The + // non-LSE versions are in atomic_aarch64.S. + void generate_atomic_entry_points() { + + if (! UseLSE) { + return; + } + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "atomic entry points"); + + __ align(32); + aarch64_atomic_fetch_add_8_impl = (aarch64_atomic_stub_t)__ pc(); + { + Register prev = r2, addr = c_rarg0, incr = c_rarg1; + __ atomic_addal(prev, incr, addr); + __ mov(r0, prev); + __ ret(lr); + } + __ align(32); + aarch64_atomic_fetch_add_4_impl = (aarch64_atomic_stub_t)__ pc(); + { + Register prev = r2, addr = c_rarg0, incr = c_rarg1; + __ atomic_addalw(prev, incr, addr); + __ movw(r0, prev); + __ ret(lr); + } + __ align(32); + aarch64_atomic_xchg_4_impl = (aarch64_atomic_stub_t)__ pc(); + { + Register prev = r2, addr = c_rarg0, newv = c_rarg1; + __ atomic_xchglw(prev, newv, addr); + __ movw(r0, prev); + __ ret(lr); + } + __ align(32); + aarch64_atomic_xchg_8_impl = (aarch64_atomic_stub_t)__ pc(); + { + Register prev = r2, addr = c_rarg0, newv = c_rarg1; + __ atomic_xchgl(prev, newv, addr); + __ mov(r0, prev); + __ ret(lr); + } + __ align(32); + aarch64_atomic_cmpxchg_1_impl = (aarch64_atomic_stub_t)__ pc(); + { + Register prev = r3, ptr = c_rarg0, compare_val = c_rarg1, + exchange_val = c_rarg2; + __ cmpxchg(ptr, compare_val, exchange_val, + MacroAssembler::byte, + /*acquire*/false, /*release*/false, /*weak*/false, + prev); + __ movw(r0, prev); + __ ret(lr); + } + __ align(32); + aarch64_atomic_cmpxchg_4_impl = (aarch64_atomic_stub_t)__ pc(); + { + Register prev = r3, ptr = c_rarg0, compare_val = c_rarg1, + exchange_val = c_rarg2; + __ cmpxchg(ptr, compare_val, exchange_val, + MacroAssembler::word, + /*acquire*/false, /*release*/false, /*weak*/false, + prev); + __ movw(r0, prev); + __ ret(lr); + } + __ align(32); + aarch64_atomic_cmpxchg_8_impl = (aarch64_atomic_stub_t)__ pc(); + { + Register prev = r3, ptr = c_rarg0, compare_val = c_rarg1, + exchange_val = c_rarg2; + __ cmpxchg(ptr, compare_val, exchange_val, + MacroAssembler::xword, + /*acquire*/false, /*release*/false, /*weak*/false, + prev); + __ mov(r0, prev); + __ ret(lr); + } + } +#endif // LINUX + // Continuation point for throwing of implicit exceptions that are // not handled in the current activation. Fabricates an exception // oop and initiates normal exception dispatching in this @@ -6881,6 +6968,14 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32(); } +#ifdef LINUX + +#if 0 // JDK-8261660: disabled for now. + generate_atomic_entry_points(); +#endif + +#endif // LINUX + StubRoutines::aarch64::set_completed(); } @@ -6901,3 +6996,27 @@ void StubGenerator_generate(CodeBuffer* code, bool all) { } StubGenerator g(code, all); } + + +#ifdef LINUX + +// Define pointers to atomic stubs and initialize them to point to the +// code in atomic_aarch64.S. + +#define DEFAULT_ATOMIC_OP(OPNAME, SIZE) \ + extern "C" uint64_t aarch64_atomic_ ## OPNAME ## _ ## SIZE ## _default_impl \ + (volatile void *ptr, uint64_t arg1, uint64_t arg2); \ + aarch64_atomic_stub_t aarch64_atomic_ ## OPNAME ## _ ## SIZE ## _impl \ + = aarch64_atomic_ ## OPNAME ## _ ## SIZE ## _default_impl; + +DEFAULT_ATOMIC_OP(fetch_add, 4) +DEFAULT_ATOMIC_OP(fetch_add, 8) +DEFAULT_ATOMIC_OP(xchg, 4) +DEFAULT_ATOMIC_OP(xchg, 8) +DEFAULT_ATOMIC_OP(cmpxchg, 1) +DEFAULT_ATOMIC_OP(cmpxchg, 4) +DEFAULT_ATOMIC_OP(cmpxchg, 8) + +#undef DEFAULT_ATOMIC_OP + +#endif // LINUX diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index 2b96b0bca96..94e8679e56c 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -46,6 +46,7 @@ #include "runtime/arguments.hpp" #include "runtime/deoptimization.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp index c5f745c5af1..a0f10db49f9 100644 --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp @@ -26,6 +26,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" #include "gc/shared/barrierSetAssembler.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/tlab_globals.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" diff --git a/src/hotspot/cpu/aarch64/vmreg_aarch64.hpp b/src/hotspot/cpu/aarch64/vmreg_aarch64.hpp index 12fab035e0c..b16202795be 100644 --- a/src/hotspot/cpu/aarch64/vmreg_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vmreg_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -34,8 +34,11 @@ inline bool is_FloatRegister() { return value() >= ConcreteRegisterImpl::max_gpr && value() < ConcreteRegisterImpl::max_fpr; } -inline Register as_Register() { +inline bool is_PRegister() { + return value() >= ConcreteRegisterImpl::max_fpr && value() < ConcreteRegisterImpl::max_pr; +} +inline Register as_Register() { assert( is_Register(), "must be"); // Yuk return ::as_Register(value() / RegisterImpl::max_slots_per_register); @@ -48,9 +51,22 @@ inline FloatRegister as_FloatRegister() { FloatRegisterImpl::max_slots_per_register); } -inline bool is_concrete() { +inline PRegister as_PRegister() { + assert( is_PRegister(), "must be" ); + return ::as_PRegister((value() - ConcreteRegisterImpl::max_fpr) / + PRegisterImpl::max_slots_per_register); +} + +inline bool is_concrete() { assert(is_reg(), "must be"); - return is_even(value()); + if (is_FloatRegister()) { + int base = value() - ConcreteRegisterImpl::max_gpr; + return base % FloatRegisterImpl::max_slots_per_register == 0; + } else if (is_PRegister()) { + return true; // Single slot + } else { + return is_even(value()); + } } #endif // CPU_AARCH64_VMREG_AARCH64_HPP diff --git a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp index 5cba07805b9..f29d4c0744c 100644 --- a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp @@ -366,9 +366,6 @@ void LIRGenerator::set_card(LIR_Opr value, LIR_Address* card_addr) { void LIRGenerator::CardTableBarrierSet_post_barrier_helper(LIR_OprDesc* addr, LIR_Const* card_table_base) { assert(addr->is_register(), "must be a register at this point"); - CardTableBarrierSet* ctbs = barrier_set_cast(BarrierSet::barrier_set()); - CardTable* ct = ctbs->card_table(); - LIR_Opr tmp = FrameMap::LR_ptr_opr; bool load_card_table_base_const = VM_Version::supports_movw(); @@ -382,9 +379,6 @@ void LIRGenerator::CardTableBarrierSet_post_barrier_helper(LIR_OprDesc* addr, LI // byte instruction does not support the addressing mode we need. LIR_Address* card_addr = new LIR_Address(tmp, addr, (LIR_Address::Scale) -CardTable::card_shift, 0, T_BOOLEAN); if (UseCondCardMark) { - if (ct->scanned_concurrently()) { - __ membar_storeload(); - } LIR_Opr cur_value = new_register(T_INT); __ move(card_addr, cur_value); @@ -394,9 +388,6 @@ void LIRGenerator::CardTableBarrierSet_post_barrier_helper(LIR_OprDesc* addr, LI set_card(tmp, card_addr); __ branch_destination(L_already_dirty->label()); } else { - if (ct->scanned_concurrently()) { - __ membar_storestore(); - } set_card(tmp, card_addr); } } diff --git a/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp b/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp index a41f36360c1..ac7137ca66d 100644 --- a/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/c1_MacroAssembler_arm.cpp @@ -205,9 +205,9 @@ int C1_MacroAssembler::lock_object(Register hdr, Register obj, null_check_offset = offset(); if (DiagnoseSyncOnValueBasedClasses != 0) { - load_klass(tmp1, obj); - ldr_u32(tmp1, Address(tmp1, Klass::access_flags_offset())); - tst(tmp1, JVM_ACC_IS_VALUE_BASED_CLASS); + load_klass(tmp2, obj); + ldr_u32(tmp2, Address(tmp2, Klass::access_flags_offset())); + tst(tmp2, JVM_ACC_IS_VALUE_BASED_CLASS); b(slow_case, ne); } diff --git a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp index ce928e9bcfd..6719c5507fe 100644 --- a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp +++ b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp @@ -31,6 +31,7 @@ #include "ci/ciUtilities.hpp" #include "gc/shared/cardTable.hpp" #include "gc/shared/cardTableBarrierSet.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/tlab_globals.hpp" #include "interpreter/interpreter.hpp" #include "memory/universe.hpp" diff --git a/src/hotspot/cpu/arm/frame_arm.cpp b/src/hotspot/cpu/arm/frame_arm.cpp index 7c7f0ca867d..31cf981c346 100644 --- a/src/hotspot/cpu/arm/frame_arm.cpp +++ b/src/hotspot/cpu/arm/frame_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -515,7 +515,7 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) } else { obj = *(oop*)res_addr; } - assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check"); + assert(Universe::is_in_heap_or_null(obj), "sanity check"); *oop_result = obj; break; } diff --git a/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp b/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp index fc32418daa8..86f43597e22 100644 --- a/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp @@ -128,16 +128,10 @@ void CardTableBarrierSetAssembler::store_check_part2(MacroAssembler* masm, Regis assert(bs->kind() == BarrierSet::CardTableBarrierSet, "Wrong barrier set kind"); - CardTableBarrierSet* ctbs = barrier_set_cast(bs); - CardTable* ct = ctbs->card_table(); - assert(CardTable::dirty_card_val() == 0, "Dirty card value must be 0 due to optimizations."); Address card_table_addr(card_table_base, obj, lsr, CardTable::card_shift); if (UseCondCardMark) { - if (ct->scanned_concurrently()) { - __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreLoad), noreg); - } Label already_dirty; __ ldrb(tmp, card_table_addr); @@ -147,9 +141,6 @@ void CardTableBarrierSetAssembler::store_check_part2(MacroAssembler* masm, Regis __ bind(already_dirty); } else { - if (ct->scanned_concurrently()) { - __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore), noreg); - } set_card(masm, card_table_base, card_table_addr, tmp); } } diff --git a/src/hotspot/cpu/arm/jniFastGetField_arm.cpp b/src/hotspot/cpu/arm/jniFastGetField_arm.cpp index 85d27f61f26..f333df57902 100644 --- a/src/hotspot/cpu/arm/jniFastGetField_arm.cpp +++ b/src/hotspot/cpu/arm/jniFastGetField_arm.cpp @@ -30,6 +30,7 @@ #include "prims/jniFastGetField.hpp" #include "prims/jvm_misc.hpp" #include "prims/jvmtiExport.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/safepoint.hpp" #define __ masm-> diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.cpp b/src/hotspot/cpu/arm/macroAssembler_arm.cpp index 1f8f62fe1dc..5843d9b956e 100644 --- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp @@ -41,6 +41,7 @@ #include "prims/methodHandles.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/interfaceSupport.inline.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/objectMonitor.hpp" #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" diff --git a/src/hotspot/cpu/arm/registerMap_arm.hpp b/src/hotspot/cpu/arm/registerMap_arm.hpp index 08a339cd14b..9f7631244b3 100644 --- a/src/hotspot/cpu/arm/registerMap_arm.hpp +++ b/src/hotspot/cpu/arm/registerMap_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,11 @@ // Since there is none, we just return NULL. // See registerMap_sparc.hpp for an example of grabbing registers // from register save areas of a standard layout. - address pd_location(VMReg reg) const {return NULL;} + address pd_location(VMReg reg) const {return NULL;} + + address pd_location(VMReg base_reg, int slot_idx) const { + return location(base_reg->next(slot_idx)); + } // no PD state to clear or copy: void pd_clear() {} diff --git a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp index 77385a9536d..b19bea1b2a1 100644 --- a/src/hotspot/cpu/arm/sharedRuntime_arm.cpp +++ b/src/hotspot/cpu/arm/sharedRuntime_arm.cpp @@ -34,6 +34,7 @@ #include "oops/compiledICHolder.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/safepointMechanism.hpp" #include "runtime/stubRoutines.hpp" diff --git a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp index d0186b591fd..f38fe198c95 100644 --- a/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/templateInterpreterGenerator_arm.cpp @@ -42,6 +42,7 @@ #include "runtime/arguments.hpp" #include "runtime/deoptimization.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" diff --git a/src/hotspot/cpu/arm/templateTable_arm.cpp b/src/hotspot/cpu/arm/templateTable_arm.cpp index c4963f30bfe..a95842ebb29 100644 --- a/src/hotspot/cpu/arm/templateTable_arm.cpp +++ b/src/hotspot/cpu/arm/templateTable_arm.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" #include "gc/shared/barrierSetAssembler.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/tlab_globals.hpp" #include "interpreter/interp_masm.hpp" #include "interpreter/interpreter.hpp" diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp index ba227011ce1..47cee695490 100644 --- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp @@ -81,6 +81,9 @@ void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_by std(return_pc, _abi0(lr), R1_SP); // SP->lr = return_pc push_frame(frame_size_in_bytes, R0); // SP -= frame_size_in_bytes + + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->nmethod_entry_barrier(this, R20); } diff --git a/src/hotspot/cpu/ppc/frame_ppc.cpp b/src/hotspot/cpu/ppc/frame_ppc.cpp index 3df8c1a2e51..81814d37be1 100644 --- a/src/hotspot/cpu/ppc/frame_ppc.cpp +++ b/src/hotspot/cpu/ppc/frame_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2017 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -305,7 +305,7 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) case T_OBJECT: case T_ARRAY: { oop obj = *(oop*)tos_addr; - assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check"); + assert(Universe::is_in_heap_or_null(obj), "sanity check"); *oop_result = obj; } case T_BOOLEAN : value_result->z = (jboolean) *(jint*)tos_addr; break; diff --git a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp index 28ff01fa017..a95197aeed7 100644 --- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp @@ -34,6 +34,7 @@ #include "gc/g1/g1ThreadLocalData.hpp" #include "gc/g1/heapRegion.hpp" #include "interpreter/interp_masm.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/sharedRuntime.hpp" #ifdef COMPILER1 #include "c1/c1_LIRAssembler.hpp" diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp index 5a092ae8af6..800b34e4ba7 100644 --- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp @@ -23,12 +23,17 @@ * */ +#include "nativeInst_ppc.hpp" #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" +#include "classfile/classLoaderData.hpp" #include "gc/shared/barrierSetAssembler.hpp" +#include "gc/shared/barrierSetNMethod.hpp" #include "interpreter/interp_masm.hpp" #include "oops/compressedOops.hpp" #include "runtime/jniHandles.hpp" +#include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" #define __ masm-> @@ -125,3 +130,69 @@ void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Re __ clrrdi(dst, obj, JNIHandles::weak_tag_size); __ ld(dst, 0, dst); // Resolve (untagged) jobject. } + +void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm, Register tmp) { + BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); + if (bs_nm == nullptr) { + return; + } + + assert_different_registers(tmp, R0); + + // Load stub address using toc (fixed instruction size, unlike load_const_optimized) + __ calculate_address_from_global_toc(tmp, StubRoutines::ppc::nmethod_entry_barrier(), + true, true, false); // 2 instructions + __ mtctr(tmp); + + // This is a compound instruction. Patching support is provided by NativeMovRegMem. + // Actual patching is done in (platform-specific part of) BarrierSetNMethod. + __ load_const32(tmp, 0 /* Value is patched */); // 2 instructions + + __ lwz(R0, in_bytes(bs_nm->thread_disarmed_offset()), R16_thread); + __ cmpw(CCR0, R0, tmp); + + __ bnectrl(CCR0); + + // Oops may have been changed; exploiting isync semantics (used as acquire) to make those updates observable. + __ isync(); +} + +void BarrierSetAssembler::c2i_entry_barrier(MacroAssembler *masm, Register tmp1, Register tmp2, Register tmp3) { + BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); + if (bs_nm == nullptr) { + return; + } + + assert_different_registers(tmp1, tmp2, tmp3); + + Register tmp1_class_loader_data = tmp1; + + Label bad_call, skip_barrier; + + // Fast path: If no method is given, the call is definitely bad. + __ cmpdi(CCR0, R19_method, 0); + __ beq(CCR0, bad_call); + + // Load class loader data to determine whether the method's holder is concurrently unloading. + __ load_method_holder(tmp1, R19_method); + __ ld(tmp1_class_loader_data, in_bytes(InstanceKlass::class_loader_data_offset()), tmp1); + + // Fast path: If class loader is strong, the holder cannot be unloaded. + __ ld(tmp2, in_bytes(ClassLoaderData::keep_alive_offset()), tmp1_class_loader_data); + __ cmpdi(CCR0, tmp2, 0); + __ bne(CCR0, skip_barrier); + + // Class loader is weak. Determine whether the holder is still alive. + __ ld(tmp2, in_bytes(ClassLoaderData::holder_offset()), tmp1_class_loader_data); + __ resolve_weak_handle(tmp2, tmp1, tmp3, MacroAssembler::PreservationLevel::PRESERVATION_FRAME_LR_GP_FP_REGS); + __ cmpdi(CCR0, tmp2, 0); + __ bne(CCR0, skip_barrier); + + __ bind(bad_call); + + __ calculate_address_from_global_toc(tmp1, SharedRuntime::get_handle_wrong_method_stub(), true, true, false); + __ mtctr(tmp1); + __ bctr(); + + __ bind(skip_barrier); +} diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp index a3e6c7eeddf..c7b0514efd2 100644 --- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp @@ -57,6 +57,9 @@ class BarrierSetAssembler: public CHeapObj { Register obj, Register tmp, Label& slowpath); virtual void barrier_stubs_init() {} + + virtual void nmethod_entry_barrier(MacroAssembler* masm, Register tmp); + virtual void c2i_entry_barrier(MacroAssembler* masm, Register tmp1, Register tmp2, Register tmp3); }; #endif // CPU_PPC_GC_SHARED_BARRIERSETASSEMBLER_PPC_HPP diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp index a0361ddc2f4..6efeb94b381 100644 --- a/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetNMethod_ppc.cpp @@ -23,18 +23,109 @@ */ #include "precompiled.hpp" +#include "code/codeBlob.hpp" +#include "code/nmethod.hpp" +#include "code/nativeInst.hpp" #include "gc/shared/barrierSetNMethod.hpp" #include "utilities/debug.hpp" +class NativeNMethodBarrier: public NativeInstruction { + + address get_barrier_start_address() const { + return NativeInstruction::addr_at(0); + } + + NativeMovRegMem* get_patchable_instruction_handle() const { + // Endianness is handled by NativeMovRegMem + return reinterpret_cast(get_barrier_start_address() + 3 * 4); + } + +public: + int get_guard_value() const { + // Retrieve the guard value (naming of 'offset' function is misleading). + return get_patchable_instruction_handle()->offset(); + } + + void release_set_guard_value(int value) { + // Patching is not atomic. + // Stale observations of the "armed" state is okay as invoking the barrier stub in that case has no + // unwanted side effects. Disarming is thus a non-critical operation. + // The visibility of the "armed" state must be ensured by safepoint/handshake. + + OrderAccess::release(); // Release modified oops + + // Set the guard value (naming of 'offset' function is misleading). + get_patchable_instruction_handle()->set_offset(value); + } + + void verify() const { + // Although it's possible to just validate the to-be-patched instruction, + // all instructions are validated to ensure that the barrier is hit properly - especially since + // the pattern used in load_const32 is a quite common one. + + uint* current_instruction = reinterpret_cast(get_barrier_start_address()); + + // calculate_address_from_global_toc (compound instruction) + verify_op_code_manually(current_instruction, MacroAssembler::is_addis(*current_instruction)); + verify_op_code_manually(current_instruction, MacroAssembler::is_addi(*current_instruction)); + + verify_op_code_manually(current_instruction, MacroAssembler::is_mtctr(*current_instruction)); + + get_patchable_instruction_handle()->verify(); + current_instruction += 2; + + verify_op_code(current_instruction, Assembler::LWZ_OPCODE); + + // cmpw (mnemonic) + verify_op_code(current_instruction, Assembler::CMP_OPCODE); + + // bnectrl (mnemonic) (weak check; not checking the exact type) + verify_op_code(current_instruction, Assembler::BCCTR_OPCODE); + + verify_op_code(current_instruction, Assembler::ISYNC_OPCODE); + } + +private: + static void verify_op_code_manually(uint*& current_instruction, bool result) { + assert(result, "illegal instruction sequence for nmethod entry barrier"); + current_instruction++; + } + static void verify_op_code(uint*& current_instruction, uint expected, + unsigned int mask = 63u << Assembler::OPCODE_SHIFT) { + // Masking both, current instruction and opcode, as some opcodes in Assembler contain additional information + // to uniquely identify simplified mnemonics. + // As long as the caller doesn't provide a custom mask, that additional information is discarded. + verify_op_code_manually(current_instruction, (*current_instruction & mask) == (expected & mask)); + } +}; + +static NativeNMethodBarrier* get_nmethod_barrier(nmethod* nm) { + address barrier_address = nm->code_begin() + nm->frame_complete_offset() + (-9 * 4); + + auto barrier = reinterpret_cast(barrier_address); + debug_only(barrier->verify()); + return barrier; +} + void BarrierSetNMethod::deoptimize(nmethod* nm, address* return_address_ptr) { - ShouldNotReachHere(); + // As PPC64 always has a valid back chain (unlike other platforms), the stub can simply pop the frame. + // Thus, there's nothing to do here. } void BarrierSetNMethod::disarm(nmethod* nm) { - ShouldNotReachHere(); + if (!supports_entry_barrier(nm)) { + return; + } + + NativeNMethodBarrier* barrier = get_nmethod_barrier(nm); + barrier->release_set_guard_value(disarmed_value()); } bool BarrierSetNMethod::is_armed(nmethod* nm) { - ShouldNotReachHere(); - return false; + if (!supports_entry_barrier(nm)) { + return false; + } + + NativeNMethodBarrier* barrier = get_nmethod_barrier(nm); + return barrier->get_guard_value() != disarmed_value(); } diff --git a/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp index fd0c4c6a540..8337317e3f2 100644 --- a/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp @@ -49,8 +49,6 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl Label Lskip_loop, Lstore_loop; - if (ct->scanned_concurrently()) { __ membar(Assembler::StoreStore); } - __ sldi_(count, count, LogBytesPerHeapOop); __ beq(CCR0, Lskip_loop); // zero length __ addi(count, count, -BytesPerHeapOop); @@ -74,13 +72,10 @@ void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembl void CardTableBarrierSetAssembler::card_table_write(MacroAssembler* masm, CardTable::CardValue* byte_map_base, Register tmp, Register obj) { - CardTableBarrierSet* ctbs = barrier_set_cast(BarrierSet::barrier_set()); - CardTable* ct = ctbs->card_table(); assert_different_registers(obj, tmp, R0); __ load_const_optimized(tmp, (address)byte_map_base, R0); __ srdi(obj, obj, CardTable::card_shift); __ li(R0, CardTable::dirty_card_val()); - if (ct->scanned_concurrently()) { __ membar(Assembler::StoreStore); } __ stbx(R0, tmp, obj); } diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc.hpp b/src/hotspot/cpu/ppc/interp_masm_ppc.hpp index fa896a2918d..f289b808150 100644 --- a/src/hotspot/cpu/ppc/interp_masm_ppc.hpp +++ b/src/hotspot/cpu/ppc/interp_masm_ppc.hpp @@ -77,7 +77,8 @@ class InterpreterMacroAssembler: public MacroAssembler { Register tmp1, Register tmp2, Register tmp3, Label &ok_is_subtype); // Load object from cpool->resolved_references(index). - void load_resolved_reference_at_index(Register result, Register index, Register tmp1, Label *L_handle_null = NULL); + void load_resolved_reference_at_index(Register result, Register index, Register tmp1, Register tmp2, + Label *L_handle_null = NULL); // load cpool->resolved_klass_at(index) void load_resolved_klass_at_offset(Register Rcpool, Register Roffset, Register Rklass); diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp index c174290a65e..6236dcb9aab 100644 --- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp @@ -477,33 +477,34 @@ void InterpreterMacroAssembler::get_u4(Register Rdst, Register Rsrc, int offset, // Load object from cpool->resolved_references(index). // Kills: // - index -void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result, Register index, Register tmp1, +void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result, Register index, + Register tmp1, Register tmp2, Label *L_handle_null) { - assert_different_registers(result, index); + assert_different_registers(result, index, tmp1, tmp2); + assert(index->is_nonvolatile(), "needs to survive C-call in resolve_oop_handle"); get_constant_pool(result); // Convert from field index to resolved_references() index and from // word index to byte offset. Since this is a java object, it can be compressed. - Register tmp2 = index; // reuse - sldi(tmp1, index, LogBytesPerHeapOop); + sldi(index, index, LogBytesPerHeapOop); // Load pointer for resolved_references[] objArray. ld(result, ConstantPool::cache_offset_in_bytes(), result); ld(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result); - resolve_oop_handle(result); + resolve_oop_handle(result, tmp1, tmp2, MacroAssembler::PRESERVATION_NONE); #ifdef ASSERT Label index_ok; lwa(R0, arrayOopDesc::length_offset_in_bytes(), result); sldi(R0, R0, LogBytesPerHeapOop); - cmpd(CCR0, tmp1, R0); + cmpd(CCR0, index, R0); blt(CCR0, index_ok); stop("resolved reference index out of bounds"); bind(index_ok); #endif // Add in the index. - add(result, tmp1, result); + add(result, index, result); load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result, tmp1, tmp2, - MacroAssembler::PRESERVATION_FRAME_LR, + MacroAssembler::PRESERVATION_NONE, 0, L_handle_null); } diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index 8ced76f08a0..555a641bde2 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -3233,16 +3233,22 @@ void MacroAssembler::load_klass(Register dst, Register src) { } // ((OopHandle)result).resolve(); -void MacroAssembler::resolve_oop_handle(Register result) { - // OopHandle::resolve is an indirection. - ld(result, 0, result); +void MacroAssembler::resolve_oop_handle(Register result, Register tmp1, Register tmp2, + MacroAssembler::PreservationLevel preservation_level) { + access_load_at(T_OBJECT, IN_NATIVE, result, noreg, result, tmp1, tmp2, preservation_level); } -void MacroAssembler::load_mirror_from_const_method(Register mirror, Register const_method) { - ld(mirror, in_bytes(ConstMethod::constants_offset()), const_method); - ld(mirror, ConstantPool::pool_holder_offset_in_bytes(), mirror); - ld(mirror, in_bytes(Klass::java_mirror_offset()), mirror); - resolve_oop_handle(mirror); +void MacroAssembler::resolve_weak_handle(Register result, Register tmp1, Register tmp2, + MacroAssembler::PreservationLevel preservation_level) { + Label resolved; + + // A null weak handle resolves to null. + cmpdi(CCR0, result, 0); + beq(CCR0, resolved); + + access_load_at(T_OBJECT, IN_NATIVE | ON_PHANTOM_OOP_REF, result, noreg, result, tmp1, tmp2, + preservation_level); + bind(resolved); } void MacroAssembler::load_method_holder(Register holder, Register method) { @@ -3373,7 +3379,7 @@ int MacroAssembler::crc32_table_columns(Register table, Register tc0, Register t assert(!VM_Version::has_vpmsumb(), "Vector version should be used instead!"); // Point to 4 byte folding tables (byte-reversed version for Big Endian) - // Layout: See StubRoutines::generate_crc_constants. + // Layout: See StubRoutines::ppc::generate_crc_constants. #ifdef VM_LITTLE_ENDIAN const int ix0 = 3 * CRC32_TABLE_SIZE; const int ix1 = 2 * CRC32_TABLE_SIZE; diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp index 4dd0ba6c34d..439d045c13f 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp @@ -743,8 +743,10 @@ class MacroAssembler: public Assembler { void store_klass(Register dst_oop, Register klass, Register tmp = R0); void store_klass_gap(Register dst_oop, Register val = noreg); // Will store 0 if val not specified. - void resolve_oop_handle(Register result); - void load_mirror_from_const_method(Register mirror, Register const_method); + void resolve_oop_handle(Register result, Register tmp1, Register tmp2, + MacroAssembler::PreservationLevel preservation_level); + void resolve_weak_handle(Register result, Register tmp1, Register tmp2, + MacroAssembler::PreservationLevel preservation_level); void load_method_holder(Register holder, Register method); static int instr_size_for_decode_klass_not_null(); diff --git a/src/hotspot/cpu/ppc/nativeInst_ppc.cpp b/src/hotspot/cpu/ppc/nativeInst_ppc.cpp index 1d53968f9f7..eece5739d5b 100644 --- a/src/hotspot/cpu/ppc/nativeInst_ppc.cpp +++ b/src/hotspot/cpu/ppc/nativeInst_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2020 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -32,6 +32,7 @@ #include "oops/oop.hpp" #include "runtime/handles.hpp" #include "runtime/orderAccess.hpp" +#include "runtime/safepoint.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/ostream.hpp" diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index cf1dfa13b90..0c3b96fa9ba 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -1376,6 +1376,10 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const { st->print("save return pc\n\t"); st->print("push frame %ld\n\t", -framesize); } + + if (C->stub_function() == NULL) { + st->print("nmethod entry barrier\n\t"); + } } #endif @@ -1529,6 +1533,11 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { __ std(return_pc, _abi0(lr), callers_sp); } + if (C->stub_function() == NULL) { + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->nmethod_entry_barrier(&_masm, push_frame_temp); + } + C->output()->set_frame_complete(cbuf.insts_size()); } diff --git a/src/hotspot/cpu/ppc/registerMap_ppc.hpp b/src/hotspot/cpu/ppc/registerMap_ppc.hpp index 973e9a32169..567028fa3e8 100644 --- a/src/hotspot/cpu/ppc/registerMap_ppc.hpp +++ b/src/hotspot/cpu/ppc/registerMap_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -35,6 +35,10 @@ // Since there is none, we just return NULL. address pd_location(VMReg reg) const { return NULL; } + address pd_location(VMReg base_reg, int slot_idx) const { + return location(base_reg->next(slot_idx)); + } + // no PD state to clear or copy: void pd_clear() {} void pd_initialize() {} diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp index 3379d679fb7..1e5cd5a5903 100644 --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp @@ -36,6 +36,7 @@ #include "oops/compiledICHolder.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/safepointMechanism.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" @@ -1300,9 +1301,13 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm c2i_no_clinit_check_entry = __ pc(); } + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->c2i_entry_barrier(masm, /* tmp register*/ ic_klass, /* tmp register*/ receiver_klass, /* tmp register*/ code); + gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, call_interpreter, ientry); - return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry); + return AdapterHandlerLibrary::new_entry(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry, + c2i_no_clinit_check_entry); } // An oop arg. Must pass a handle not the oop itself. @@ -1972,6 +1977,10 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, __ generate_stack_overflow_check(frame_size_in_bytes); // Check before creating frame. __ mr(r_callers_sp, R1_SP); // Remember frame pointer. __ push_frame(frame_size_in_bytes, r_temp_1); // Push the c2n adapter's frame. + + BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); + bs->nmethod_entry_barrier(masm, r_temp_1); + frame_done_pc = (intptr_t)__ pc(); __ verify_thread(); diff --git a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp index f38e02d46e2..f762f62e226 100644 --- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp @@ -27,6 +27,7 @@ #include "asm/macroAssembler.inline.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" +#include "gc/shared/barrierSetNMethod.hpp" #include "interpreter/interpreter.hpp" #include "nativeInst_ppc.hpp" #include "oops/instanceOop.hpp" @@ -3548,6 +3549,54 @@ class StubGenerator: public StubCodeGenerator { return start; } + address generate_nmethod_entry_barrier() { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "nmethod_entry_barrier"); + + address stub_address = __ pc(); + + int nbytes_save = MacroAssembler::num_volatile_regs * BytesPerWord; + __ save_volatile_gprs(R1_SP, -nbytes_save, true); + + // Link register points to instruction in prologue of the guarded nmethod. + // As the stub requires one layer of indirection (argument is of type address* and not address), + // passing the link register's value directly doesn't work. + // Since we have to save the link register on the stack anyway, we calculate the corresponding stack address + // and pass that one instead. + __ add(R3_ARG1, _abi0(lr), R1_SP); + + __ save_LR_CR(R0); + __ push_frame_reg_args(nbytes_save, R0); + + __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSetNMethod::nmethod_stub_entry_barrier)); + __ mr(R0, R3_RET); + + __ pop_frame(); + __ restore_LR_CR(R3_RET /* used as tmp register */); + __ restore_volatile_gprs(R1_SP, -nbytes_save, true); + + __ cmpdi(CCR0, R0, 0); + + // Return to prologue if no deoptimization is required (bnelr) + __ bclr(Assembler::bcondCRbiIs1, Assembler::bi0(CCR0, Assembler::equal), Assembler::bhintIsTaken); + + // Deoptimization required. + // For actually handling the deoptimization, the 'wrong method stub' is invoked. + __ load_const_optimized(R0, SharedRuntime::get_handle_wrong_method_stub()); + __ mtctr(R0); + + // Pop the frame built in the prologue. + __ pop_frame(); + + // Restore link register. Required as the 'wrong method stub' needs the caller's frame + // to properly deoptimize this method (e.g. by re-resolving the call site for compiled methods). + // This method's prologue is aborted. + __ restore_LR_CR(R0); + + __ bctr(); + return stub_address; + } + #ifdef VM_LITTLE_ENDIAN // The following Base64 decode intrinsic is based on an algorithm outlined // in here: @@ -4462,13 +4511,13 @@ class StubGenerator: public StubCodeGenerator { // CRC32 Intrinsics. if (UseCRC32Intrinsics) { - StubRoutines::_crc_table_adr = StubRoutines::generate_crc_constants(REVERSE_CRC32_POLY); + StubRoutines::_crc_table_adr = StubRoutines::ppc::generate_crc_constants(REVERSE_CRC32_POLY); StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes(false); } // CRC32C Intrinsics. if (UseCRC32CIntrinsics) { - StubRoutines::_crc32c_table_addr = StubRoutines::generate_crc_constants(REVERSE_CRC32C_POLY); + StubRoutines::_crc32c_table_addr = StubRoutines::ppc::generate_crc_constants(REVERSE_CRC32C_POLY); StubRoutines::_updateBytesCRC32C = generate_CRC32_updateBytes(true); } @@ -4494,6 +4543,12 @@ class StubGenerator: public StubCodeGenerator { // support for verify_oop (must happen after universe_init) StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop(); + // nmethod entry barriers for concurrent class unloading + BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); + if (bs_nm != NULL) { + StubRoutines::ppc::_nmethod_entry_barrier = generate_nmethod_entry_barrier(); + } + // arraycopy stubs used by compilers generate_arraycopy_stubs(); diff --git a/src/hotspot/cpu/ppc/stubRoutines_ppc.hpp b/src/hotspot/cpu/ppc/stubRoutines_ppc.hpp index c773ae70bf8..cdffe5818c4 100644 --- a/src/hotspot/cpu/ppc/stubRoutines_ppc.hpp +++ b/src/hotspot/cpu/ppc/stubRoutines_ppc.hpp @@ -46,6 +46,16 @@ enum platform_dependent_constants { #define CRC32_UNROLL_FACTOR 2048 #define CRC32_UNROLL_FACTOR2 8 -static address generate_crc_constants(juint reverse_poly); +class ppc { + friend class StubGenerator; + + private: + static address _nmethod_entry_barrier; + + public: + static address nmethod_entry_barrier(); + + static address generate_crc_constants(juint reverse_poly); +}; #endif // CPU_PPC_STUBROUTINES_PPC_HPP diff --git a/src/hotspot/cpu/ppc/stubRoutines_ppc_64.cpp b/src/hotspot/cpu/ppc/stubRoutines_ppc_64.cpp index a935d64ef59..1570a76f044 100644 --- a/src/hotspot/cpu/ppc/stubRoutines_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/stubRoutines_ppc_64.cpp @@ -80,7 +80,7 @@ static void reverse_bytes(juint &w) { #endif // Constants to fold n words as needed by macroAssembler. -address StubRoutines::generate_crc_constants(juint reverse_poly) { +address StubRoutines::ppc::generate_crc_constants(juint reverse_poly) { // Layout of constant table: // <= Power7 Little Endian: 4 tables for byte folding // <= Power7 Big Endian: 1 table for single byte folding + 4 tables for multi-byte folding @@ -210,3 +210,8 @@ address StubRoutines::generate_crc_constants(juint reverse_poly) { return consts; } + +address StubRoutines::ppc::_nmethod_entry_barrier = nullptr; +address StubRoutines::ppc::nmethod_entry_barrier() { + return _nmethod_entry_barrier; +} diff --git a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp index ed95650255c..5a74b8ca1b0 100644 --- a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp @@ -42,6 +42,7 @@ #include "runtime/arguments.hpp" #include "runtime/deoptimization.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" @@ -932,11 +933,14 @@ void TemplateInterpreterGenerator::lock_method(Register Rflags, Register Rscratc // state_size: We save the current state of the interpreter to this area. // void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call, Register Rsize_of_parameters, Register Rsize_of_locals) { - Register parent_frame_resize = R6_ARG4, // Frame will grow by this number of bytes. - top_frame_size = R7_ARG5, - Rconst_method = R8_ARG6; + Register Rparent_frame_resize = R6_ARG4, // Frame will grow by this number of bytes. + Rtop_frame_size = R7_ARG5, + Rconst_method = R8_ARG6, + Rconst_pool = R9_ARG7, + Rmirror = R10_ARG8; - assert_different_registers(Rsize_of_parameters, Rsize_of_locals, parent_frame_resize, top_frame_size); + assert_different_registers(Rsize_of_parameters, Rsize_of_locals, Rparent_frame_resize, Rtop_frame_size, + Rconst_method, Rconst_pool); __ ld(Rconst_method, method_(const)); __ lhz(Rsize_of_parameters /* number of params */, @@ -947,35 +951,35 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call, Regist // We add two slots to the parameter_count, one for the jni // environment and one for a possible native mirror. Label skip_native_calculate_max_stack; - __ addi(top_frame_size, Rsize_of_parameters, 2); - __ cmpwi(CCR0, top_frame_size, Argument::n_register_parameters); + __ addi(Rtop_frame_size, Rsize_of_parameters, 2); + __ cmpwi(CCR0, Rtop_frame_size, Argument::n_register_parameters); __ bge(CCR0, skip_native_calculate_max_stack); - __ li(top_frame_size, Argument::n_register_parameters); + __ li(Rtop_frame_size, Argument::n_register_parameters); __ bind(skip_native_calculate_max_stack); __ sldi(Rsize_of_parameters, Rsize_of_parameters, Interpreter::logStackElementSize); - __ sldi(top_frame_size, top_frame_size, Interpreter::logStackElementSize); - __ sub(parent_frame_resize, R1_SP, R15_esp); // <0, off by Interpreter::stackElementSize! + __ sldi(Rtop_frame_size, Rtop_frame_size, Interpreter::logStackElementSize); + __ sub(Rparent_frame_resize, R1_SP, R15_esp); // <0, off by Interpreter::stackElementSize! assert(Rsize_of_locals == noreg, "Rsize_of_locals not initialized"); // Only relevant value is Rsize_of_parameters. } else { __ lhz(Rsize_of_locals /* number of params */, in_bytes(ConstMethod::size_of_locals_offset()), Rconst_method); __ sldi(Rsize_of_parameters, Rsize_of_parameters, Interpreter::logStackElementSize); __ sldi(Rsize_of_locals, Rsize_of_locals, Interpreter::logStackElementSize); - __ lhz(top_frame_size, in_bytes(ConstMethod::max_stack_offset()), Rconst_method); + __ lhz(Rtop_frame_size, in_bytes(ConstMethod::max_stack_offset()), Rconst_method); __ sub(R11_scratch1, Rsize_of_locals, Rsize_of_parameters); // >=0 - __ sub(parent_frame_resize, R1_SP, R15_esp); // <0, off by Interpreter::stackElementSize! - __ sldi(top_frame_size, top_frame_size, Interpreter::logStackElementSize); - __ add(parent_frame_resize, parent_frame_resize, R11_scratch1); + __ sub(Rparent_frame_resize, R1_SP, R15_esp); // <0, off by Interpreter::stackElementSize! + __ sldi(Rtop_frame_size, Rtop_frame_size, Interpreter::logStackElementSize); + __ add(Rparent_frame_resize, Rparent_frame_resize, R11_scratch1); } // Compute top frame size. - __ addi(top_frame_size, top_frame_size, frame::abi_reg_args_size + frame::ijava_state_size); + __ addi(Rtop_frame_size, Rtop_frame_size, frame::abi_reg_args_size + frame::ijava_state_size); // Cut back area between esp and max_stack. - __ addi(parent_frame_resize, parent_frame_resize, frame::abi_minframe_size - Interpreter::stackElementSize); + __ addi(Rparent_frame_resize, Rparent_frame_resize, frame::abi_minframe_size - Interpreter::stackElementSize); - __ round_to(top_frame_size, frame::alignment_in_bytes); - __ round_to(parent_frame_resize, frame::alignment_in_bytes); - // parent_frame_resize = (locals-parameters) - (ESP-SP-ABI48) Rounded to frame alignment size. + __ round_to(Rtop_frame_size, frame::alignment_in_bytes); + __ round_to(Rparent_frame_resize, frame::alignment_in_bytes); + // Rparent_frame_resize = (locals-parameters) - (ESP-SP-ABI48) Rounded to frame alignment size. // Enlarge by locals-parameters (not in case of native_call), shrink by ESP-SP-ABI48. if (!native_call) { @@ -983,15 +987,15 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call, Regist // Native calls don't need the stack size check since they have no // expression stack and the arguments are already on the stack and // we only add a handful of words to the stack. - __ add(R11_scratch1, parent_frame_resize, top_frame_size); + __ add(R11_scratch1, Rparent_frame_resize, Rtop_frame_size); generate_stack_overflow_check(R11_scratch1, R12_scratch2); } // Set up interpreter state registers. __ add(R18_locals, R15_esp, Rsize_of_parameters); - __ ld(R27_constPoolCache, in_bytes(ConstMethod::constants_offset()), Rconst_method); - __ ld(R27_constPoolCache, ConstantPool::cache_offset_in_bytes(), R27_constPoolCache); + __ ld(Rconst_pool, in_bytes(ConstMethod::constants_offset()), Rconst_method); + __ ld(R27_constPoolCache, ConstantPool::cache_offset_in_bytes(), Rconst_pool); // Set method data pointer. if (ProfileInterpreter) { @@ -1011,19 +1015,21 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call, Regist // Resize parent frame. __ mflr(R12_scratch2); - __ neg(parent_frame_resize, parent_frame_resize); - __ resize_frame(parent_frame_resize, R11_scratch1); + __ neg(Rparent_frame_resize, Rparent_frame_resize); + __ resize_frame(Rparent_frame_resize, R11_scratch1); __ std(R12_scratch2, _abi0(lr), R1_SP); // Get mirror and store it in the frame as GC root for this Method*. - __ load_mirror_from_const_method(R12_scratch2, Rconst_method); + __ ld(Rmirror, ConstantPool::pool_holder_offset_in_bytes(), Rconst_pool); + __ ld(Rmirror, in_bytes(Klass::java_mirror_offset()), Rmirror); + __ resolve_oop_handle(Rmirror, R11_scratch1, R12_scratch2, MacroAssembler::PRESERVATION_FRAME_LR_GP_REGS); __ addi(R26_monitor, R1_SP, -frame::ijava_state_size); __ addi(R15_esp, R26_monitor, -Interpreter::stackElementSize); // Store values. __ std(R19_method, _ijava_state_neg(method), R1_SP); - __ std(R12_scratch2, _ijava_state_neg(mirror), R1_SP); + __ std(Rmirror, _ijava_state_neg(mirror), R1_SP); __ std(R18_locals, _ijava_state_neg(locals), R1_SP); __ std(R27_constPoolCache, _ijava_state_neg(cpoolCache), R1_SP); @@ -1045,12 +1051,12 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call, Regist __ std(R0, _ijava_state_neg(oop_tmp), R1_SP); // only used for native_call // Store sender's SP and this frame's top SP. - __ subf(R12_scratch2, top_frame_size, R1_SP); + __ subf(R12_scratch2, Rtop_frame_size, R1_SP); __ std(R21_sender_SP, _ijava_state_neg(sender_sp), R1_SP); __ std(R12_scratch2, _ijava_state_neg(top_frame_sp), R1_SP); // Push top frame. - __ push_frame(top_frame_size, R11_scratch1); + __ push_frame(Rtop_frame_size, R11_scratch1); } // End of helpers diff --git a/src/hotspot/cpu/ppc/templateTable_ppc.hpp b/src/hotspot/cpu/ppc/templateTable_ppc.hpp index 0ab9814ebae..afe10c2d6fd 100644 --- a/src/hotspot/cpu/ppc/templateTable_ppc.hpp +++ b/src/hotspot/cpu/ppc/templateTable_ppc.hpp @@ -26,7 +26,8 @@ #ifndef CPU_PPC_TEMPLATETABLE_PPC_HPP #define CPU_PPC_TEMPLATETABLE_PPC_HPP - static void prepare_invoke(int byte_no, Register Rmethod, Register Rret_addr, Register Rindex, Register Rrecv, Register Rflags, Register Rscratch); + static void prepare_invoke(int byte_no, Register Rmethod, Register Rret_addr, Register Rindex, Register Rrecv, Register Rflags, + Register Rscratch1, Register Rscratch2); static void invokevfinal_helper(Register Rmethod, Register Rflags, Register Rscratch1, Register Rscratch2); static void generate_vtable_call(Register Rrecv_klass, Register Rindex, Register Rret, Register Rtemp); static void invokeinterface_object_method(Register Rrecv_klass, Register Rret, Register Rflags, Register Rindex, Register Rtemp, Register Rtemp2); diff --git a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp index d5916eb0a73..70a805d3484 100644 --- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp @@ -309,14 +309,14 @@ void TemplateTable::fast_aldc(bool wide) { // We are resolved if the resolved reference cache entry contains a // non-null object (CallSite, etc.) - __ get_cache_index_at_bcp(R11_scratch1, 1, index_size); // Load index. - __ load_resolved_reference_at_index(R17_tos, R11_scratch1, R12_scratch2, &is_null); + __ get_cache_index_at_bcp(R31, 1, index_size); // Load index. + __ load_resolved_reference_at_index(R17_tos, R31, R11_scratch1, R12_scratch2, &is_null); // Convert null sentinel to NULL int simm16_rest = __ load_const_optimized(R11_scratch1, Universe::the_null_sentinel_addr(), R0, true); - __ ld(R11_scratch1, simm16_rest, R11_scratch1); - __ resolve_oop_handle(R11_scratch1); - __ cmpld(CCR0, R17_tos, R11_scratch1); + __ ld(R31, simm16_rest, R11_scratch1); + __ resolve_oop_handle(R31, R11_scratch1, R12_scratch2, MacroAssembler::PRESERVATION_NONE); + __ cmpld(CCR0, R17_tos, R31); if (VM_Version::has_isel()) { __ isel_0(R17_tos, CCR0, Assembler::equal); } else { @@ -2252,14 +2252,16 @@ void TemplateTable::resolve_cache_and_index(int byte_no, Register Rcache, Regist // - Rcache, Rindex // Output: // - Robj, Roffset, Rflags +// Kills: +// - R11, R12 void TemplateTable::load_field_cp_cache_entry(Register Robj, Register Rcache, Register Rindex /* unused on PPC64 */, Register Roffset, Register Rflags, - bool is_static = false) { - assert_different_registers(Rcache, Rflags, Roffset); - // assert(Rindex == noreg, "parameter not used on PPC64"); + bool is_static) { + assert_different_registers(Rcache, Rflags, Roffset, R11_scratch1, R12_scratch2); + assert(Rindex == noreg, "parameter not used on PPC64"); ByteSize cp_base_offset = ConstantPoolCache::base_offset(); __ ld(Rflags, in_bytes(cp_base_offset) + in_bytes(ConstantPoolCacheEntry::flags_offset()), Rcache); @@ -2267,7 +2269,7 @@ void TemplateTable::load_field_cp_cache_entry(Register Robj, if (is_static) { __ ld(Robj, in_bytes(cp_base_offset) + in_bytes(ConstantPoolCacheEntry::f1_offset()), Rcache); __ ld(Robj, in_bytes(Klass::java_mirror_offset()), Robj); - __ resolve_oop_handle(Robj); + __ resolve_oop_handle(Robj, R11_scratch1, R12_scratch2, MacroAssembler::PRESERVATION_NONE); // Acquire not needed here. Following access has an address dependency on this value. } } @@ -2427,7 +2429,8 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr Rflags = R31, Rbtable = R5_ARG3, Rbc = R30, - Rscratch = R12_scratch2; + Rscratch = R11_scratch1; // used by load_field_cp_cache_entry + // R12_scratch2 used by load_field_cp_cache_entry static address field_branch_table[number_of_states], static_branch_table[number_of_states]; @@ -2441,7 +2444,7 @@ void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteContr jvmti_post_field_access(Rcache, Rscratch, is_static, false); // Load after possible GC. - load_field_cp_cache_entry(Rclass_or_obj, Rcache, noreg, Roffset, Rflags, is_static); + load_field_cp_cache_entry(Rclass_or_obj, Rcache, noreg, Roffset, Rflags, is_static); // Uses R11, R12 // Load pointer to branch table. __ load_const_optimized(Rbtable, (address)branch_table, Rscratch); @@ -2758,10 +2761,10 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr const Register Rcache = R5_ARG3, // Do not use ARG1/2 (causes trouble in jvmti_post_field_mod). Rclass_or_obj = R31, // Needs to survive C call. Roffset = R22_tmp2, // Needs to survive C call. - Rflags = R3_ARG1, + Rflags = R30, Rbtable = R4_ARG2, - Rscratch = R11_scratch1, - Rscratch2 = R12_scratch2, + Rscratch = R11_scratch1, // used by load_field_cp_cache_entry + Rscratch2 = R12_scratch2, // used by load_field_cp_cache_entry Rscratch3 = R6_ARG4, Rbc = Rscratch3; const ConditionRegister CR_is_vol = CCR2; // Non-volatile condition register (survives runtime call in do_oop_store). @@ -2780,7 +2783,7 @@ void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteContr // Load the field offset. resolve_cache_and_index(byte_no, Rcache, Rscratch, sizeof(u2)); jvmti_post_field_mod(Rcache, Rscratch, is_static); - load_field_cp_cache_entry(Rclass_or_obj, Rcache, noreg, Roffset, Rflags, is_static); + load_field_cp_cache_entry(Rclass_or_obj, Rcache, noreg, Roffset, Rflags, is_static); // Uses R11, R12 // Load pointer to branch table. __ load_const_optimized(Rbtable, (address)branch_table, Rscratch); @@ -3007,15 +3010,15 @@ void TemplateTable::fast_storefield(TosState state) { Rclass_or_obj = R31, // Needs to survive C call. Roffset = R22_tmp2, // Needs to survive C call. Rflags = R3_ARG1, - Rscratch = R11_scratch1, - Rscratch2 = R12_scratch2, + Rscratch = R11_scratch1, // used by load_field_cp_cache_entry + Rscratch2 = R12_scratch2, // used by load_field_cp_cache_entry Rscratch3 = R4_ARG2; const ConditionRegister CR_is_vol = CCR2; // Non-volatile condition register (survives runtime call in do_oop_store). // Constant pool already resolved => Load flags and offset of field. __ get_cache_and_index_at_bcp(Rcache, 1); jvmti_post_field_mod(Rcache, Rscratch, false /* not static */); - load_field_cp_cache_entry(noreg, Rcache, noreg, Roffset, Rflags, false); + load_field_cp_cache_entry(noreg, Rcache, noreg, Roffset, Rflags, false); // Uses R11, R12 // Get the obj and the final store addr. pop_and_check_object(Rclass_or_obj); // Kills R11_scratch1. @@ -3090,11 +3093,12 @@ void TemplateTable::fast_accessfield(TosState state) { Rclass_or_obj = R17_tos, Roffset = R22_tmp2, Rflags = R23_tmp3, - Rscratch = R12_scratch2; + Rscratch = R11_scratch1; // used by load_field_cp_cache_entry + // R12_scratch2 used by load_field_cp_cache_entry // Constant pool already resolved. Get the field offset. __ get_cache_and_index_at_bcp(Rcache, 1); - load_field_cp_cache_entry(noreg, Rcache, noreg, Roffset, Rflags, false); + load_field_cp_cache_entry(noreg, Rcache, noreg, Roffset, Rflags, false); // Uses R11, R12 // JVMTI support jvmti_post_field_access(Rcache, Rscratch, false, true); @@ -3226,13 +3230,14 @@ void TemplateTable::fast_xaccess(TosState state) { Rclass_or_obj = R17_tos, Roffset = R22_tmp2, Rflags = R23_tmp3, - Rscratch = R12_scratch2; + Rscratch = R11_scratch1; + // R12_scratch2 used by load_field_cp_cache_entry __ ld(Rclass_or_obj, 0, R18_locals); // Constant pool already resolved. Get the field offset. __ get_cache_and_index_at_bcp(Rcache, 2); - load_field_cp_cache_entry(noreg, Rcache, noreg, Roffset, Rflags, false); + load_field_cp_cache_entry(noreg, Rcache, noreg, Roffset, Rflags, false); // Uses R11, R12 // JVMTI support not needed, since we switch back to single bytecode as soon as debugger attaches. @@ -3317,7 +3322,8 @@ void TemplateTable::prepare_invoke(int byte_no, Register Rindex, // itable index, MethodType, Method, etc. Register Rrecv, // If caller wants to see it. Register Rflags, // If caller wants to test it. - Register Rscratch + Register Rscratch1, + Register Rscratch2 ) { // Determine flags. const Bytecodes::Code code = bytecode(); @@ -3329,10 +3335,9 @@ void TemplateTable::prepare_invoke(int byte_no, const bool load_receiver = (Rrecv != noreg); assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic), ""); - assert_different_registers(Rmethod, Rindex, Rflags, Rscratch); - assert_different_registers(Rmethod, Rrecv, Rflags, Rscratch); - // Rret_addr and Rindex have to be distinct as Rret_addr is used as a second temp register - assert_different_registers(Rret_addr, Rindex, Rscratch); + assert_different_registers(Rmethod, Rindex, Rflags, Rscratch1); + assert_different_registers(Rmethod, Rrecv, Rflags, Rscratch1); + assert_different_registers(Rret_addr, Rscratch1); load_invoke_cp_cache_entry(byte_no, Rmethod, Rindex, Rflags, is_invokevirtual, false, is_invokedynamic); @@ -3341,22 +3346,23 @@ void TemplateTable::prepare_invoke(int byte_no, // Maybe push "appendix" to arguments. if (is_invokedynamic || is_invokehandle) { Label Ldone; - Register reference = Rret_addr; // safe to use here; first use comes later + Register reference = Rscratch1; __ rldicl_(R0, Rflags, 64-ConstantPoolCacheEntry::has_appendix_shift, 63); __ beq(CCR0, Ldone); // Push "appendix" (MethodType, CallSite, etc.). // This must be done before we get the receiver, // since the parameter_size includes it. - __ load_resolved_reference_at_index(reference, Rindex, Rscratch); + __ load_resolved_reference_at_index(reference, Rindex, /* temp */ Rret_addr, Rscratch2); __ verify_oop(reference); __ push_ptr(reference); + __ bind(Ldone); } // Load receiver if needed (after appendix is pushed so parameter size is correct). if (load_receiver) { - const Register Rparam_count = Rscratch; + Register Rparam_count = Rscratch1; __ andi(Rparam_count, Rflags, ConstantPoolCacheEntry::parameter_size_mask); __ load_receiver(Rparam_count, Rrecv); __ verify_oop(Rrecv); @@ -3364,7 +3370,7 @@ void TemplateTable::prepare_invoke(int byte_no, // Get return address. { - Register Rtable_addr = Rscratch; + Register Rtable_addr = Rscratch1; Register Rret_type = Rret_addr; address table_addr = (address) Interpreter::invoke_return_entry_table_for(code); @@ -3495,7 +3501,7 @@ void TemplateTable::invokespecial(int byte_no) { Rreceiver = R6_ARG4, Rmethod = R31; - prepare_invoke(byte_no, Rmethod, Rret_addr, noreg, Rreceiver, Rflags, R11_scratch1); + prepare_invoke(byte_no, Rmethod, Rret_addr, noreg, Rreceiver, Rflags, R11_scratch1, R12_scratch2); // Receiver NULL check. __ null_check_throw(Rreceiver, -1, R11_scratch1); @@ -3514,7 +3520,7 @@ void TemplateTable::invokestatic(int byte_no) { Rret_addr = R4_ARG2, Rflags = R5_ARG3; - prepare_invoke(byte_no, R19_method, Rret_addr, noreg, noreg, Rflags, R11_scratch1); + prepare_invoke(byte_no, R19_method, Rret_addr, noreg, noreg, Rflags, R11_scratch1, R12_scratch2); __ profile_call(R11_scratch1, R12_scratch2); // Argument and return type profiling. @@ -3566,7 +3572,7 @@ void TemplateTable::invokeinterface(int byte_no) { Rrecv_klass = R4_ARG2, Rflags = R7_ARG5; - prepare_invoke(byte_no, Rinterface_klass, Rret_addr, Rmethod, Rreceiver, Rflags, Rscratch1); + prepare_invoke(byte_no, Rinterface_klass, Rret_addr, Rmethod, Rreceiver, Rflags, Rscratch1, /* temp */ Rrecv_klass); // First check for Object case, then private interface method, // then regular interface method. @@ -3653,10 +3659,11 @@ void TemplateTable::invokedynamic(int byte_no) { const Register Rret_addr = R3_ARG1, Rflags = R31, Rmethod = R22_tmp2, - Rscratch1 = R11_scratch1, - Rscratch2 = R12_scratch2; + Rscratch1 = R30, + Rscratch2 = R11_scratch1, + Rscratch3 = R12_scratch2; - prepare_invoke(byte_no, Rmethod, Rret_addr, Rscratch1, noreg, Rflags, Rscratch2); + prepare_invoke(byte_no, Rmethod, Rret_addr, Rscratch1, noreg, Rflags, Rscratch2, Rscratch3); // Profile this call. __ profile_call(Rscratch1, Rscratch2); @@ -3678,10 +3685,11 @@ void TemplateTable::invokehandle(int byte_no) { Rflags = R31, Rrecv = R5_ARG3, Rmethod = R22_tmp2, - Rscratch1 = R11_scratch1, - Rscratch2 = R12_scratch2; + Rscratch1 = R30, + Rscratch2 = R11_scratch1, + Rscratch3 = R12_scratch2; - prepare_invoke(byte_no, Rmethod, Rret_addr, Rscratch1, Rrecv, Rflags, Rscratch2); + prepare_invoke(byte_no, Rmethod, Rret_addr, Rscratch1, Rrecv, Rflags, Rscratch2, Rscratch3); __ verify_method_ptr(Rmethod); __ null_check_throw(Rrecv, -1, Rscratch2); diff --git a/src/hotspot/cpu/s390/frame_s390.cpp b/src/hotspot/cpu/s390/frame_s390.cpp index fa0e81673d3..3f232c2ef21 100644 --- a/src/hotspot/cpu/s390/frame_s390.cpp +++ b/src/hotspot/cpu/s390/frame_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -318,7 +318,7 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) case T_OBJECT: case T_ARRAY: { oop obj = *(oop*)tos_addr; - assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check"); + assert(Universe::is_in_heap_or_null(obj), "sanity check"); *oop_result = obj; break; } diff --git a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp index 2735aa24e72..ba4bfdc9864 100644 --- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp @@ -35,6 +35,7 @@ #include "gc/g1/g1ThreadLocalData.hpp" #include "gc/g1/heapRegion.hpp" #include "interpreter/interp_masm.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/sharedRuntime.hpp" #ifdef COMPILER1 #include "c1/c1_LIRAssembler.hpp" diff --git a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp index 99cafd8bbdd..a6dc2f90e53 100644 --- a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp @@ -28,6 +28,7 @@ #include "gc/shared/barrierSetAssembler.hpp" #include "interpreter/interp_masm.hpp" #include "oops/compressedOops.hpp" +#include "runtime/jniHandles.hpp" #define __ masm-> diff --git a/src/hotspot/cpu/s390/registerMap_s390.hpp b/src/hotspot/cpu/s390/registerMap_s390.hpp index d2d60bce925..6fa7a5a12da 100644 --- a/src/hotspot/cpu/s390/registerMap_s390.hpp +++ b/src/hotspot/cpu/s390/registerMap_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -34,7 +34,11 @@ // This is the hook for finding a register in a "well-known" location, // such as a register block of a predetermined format. // Since there is none, we just return NULL. - address pd_location(VMReg reg) const {return NULL;} + address pd_location(VMReg reg) const {return NULL;} + + address pd_location(VMReg base_reg, int slot_idx) const { + return location(base_reg->next(slot_idx)); + } // No PD state to clear or copy. void pd_clear() {} diff --git a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp index e91c7492758..79980aeb670 100644 --- a/src/hotspot/cpu/s390/sharedRuntime_s390.cpp +++ b/src/hotspot/cpu/s390/sharedRuntime_s390.cpp @@ -37,6 +37,7 @@ #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" #include "registerSaver_s390.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/safepointMechanism.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" diff --git a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp index 77753e495be..bcceabb4105 100644 --- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp @@ -42,6 +42,7 @@ #include "runtime/arguments.hpp" #include "runtime/deoptimization.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" diff --git a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp index d8ad69faeed..af5b91f3fb0 100644 --- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp +++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp @@ -30,6 +30,7 @@ #include "ci/ciUtilities.hpp" #include "gc/shared/cardTable.hpp" #include "gc/shared/cardTableBarrierSet.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/tlab_globals.hpp" #include "interpreter/interpreter.hpp" #include "memory/universe.hpp" diff --git a/src/hotspot/cpu/x86/frame_x86.cpp b/src/hotspot/cpu/x86/frame_x86.cpp index 9b11e4ca275..e7d8c98d8ca 100644 --- a/src/hotspot/cpu/x86/frame_x86.cpp +++ b/src/hotspot/cpu/x86/frame_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "vmreg_x86.inline.hpp" +#include "utilities/formatBuffer.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" #include "runtime/vframeArray.hpp" @@ -629,7 +630,7 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) oop* obj_p = (oop*)tos_addr; obj = (obj_p == NULL) ? (oop)NULL : *obj_p; } - assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check"); + assert(Universe::is_in_heap_or_null(obj), "sanity check"); *oop_result = obj; break; } diff --git a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp index f1982f86649..c46f6742ef2 100644 --- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" +#include "classfile/classLoaderData.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/barrierSetAssembler.hpp" #include "gc/shared/barrierSetNMethod.hpp" diff --git a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp index 25ca3b39ce4..49d8d06fb06 100644 --- a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp @@ -118,9 +118,6 @@ void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register ob int dirty = CardTable::dirty_card_val(); if (UseCondCardMark) { Label L_already_dirty; - if (ct->scanned_concurrently()) { - __ membar(Assembler::StoreLoad); - } __ cmpb(card_addr, dirty); __ jcc(Assembler::equal, L_already_dirty); __ movb(card_addr, dirty); diff --git a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp index 56c1bbdc34a..7728d32e558 100644 --- a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp +++ b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp @@ -26,6 +26,7 @@ #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/sharedRuntime.hpp" #include "jvmci/jvmci.hpp" #include "jvmci/jvmciEnv.hpp" diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index ee4a95729a4..1d31c014450 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -43,6 +43,7 @@ #include "runtime/biasedLocking.hpp" #include "runtime/flags/flagSetting.hpp" #include "runtime/interfaceSupport.inline.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/objectMonitor.hpp" #include "runtime/os.hpp" #include "runtime/safepoint.hpp" diff --git a/src/hotspot/cpu/x86/methodHandles_x86.cpp b/src/hotspot/cpu/x86/methodHandles_x86.cpp index 7c2a0b88821..b0af94b75dc 100644 --- a/src/hotspot/cpu/x86/methodHandles_x86.cpp +++ b/src/hotspot/cpu/x86/methodHandles_x86.cpp @@ -39,6 +39,7 @@ #include "runtime/flags/flagSetting.hpp" #include "runtime/frame.inline.hpp" #include "runtime/stubRoutines.hpp" +#include "utilities/formatBuffer.hpp" #include "utilities/preserveException.hpp" #define __ Disassembler::hook(__FILE__, __LINE__, _masm)-> diff --git a/src/hotspot/cpu/x86/nativeInst_x86.cpp b/src/hotspot/cpu/x86/nativeInst_x86.cpp index 1ac15489562..fb00defc99e 100644 --- a/src/hotspot/cpu/x86/nativeInst_x86.cpp +++ b/src/hotspot/cpu/x86/nativeInst_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "nativeInst_x86.hpp" #include "oops/oop.inline.hpp" #include "runtime/handles.hpp" +#include "runtime/safepoint.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/ostream.hpp" diff --git a/src/hotspot/cpu/x86/registerMap_x86.cpp b/src/hotspot/cpu/x86/registerMap_x86.cpp index fd091262c29..3acbb98bf76 100644 --- a/src/hotspot/cpu/x86/registerMap_x86.cpp +++ b/src/hotspot/cpu/x86/registerMap_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,3 +61,7 @@ address RegisterMap::pd_location(VMReg reg) const { } return NULL; } + +address RegisterMap::pd_location(VMReg base_reg, int slot_idx) const { + return location(base_reg->next(slot_idx)); +} diff --git a/src/hotspot/cpu/x86/registerMap_x86.hpp b/src/hotspot/cpu/x86/registerMap_x86.hpp index 7806c5a71c0..8ab259c777c 100644 --- a/src/hotspot/cpu/x86/registerMap_x86.hpp +++ b/src/hotspot/cpu/x86/registerMap_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ // This is the hook for finding a register in an "well-known" location, // such as a register block of a predetermined format. address pd_location(VMReg reg) const; + address pd_location(VMReg base_reg, int slot_idx) const; // no PD state to clear or copy: void pd_clear() {} void pd_initialize() {} diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp index bba37f9e895..3288a4b8b8f 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_32.cpp @@ -38,6 +38,7 @@ #include "oops/compiledICHolder.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/safepointMechanism.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index 34a7eb0602f..5474655bfd9 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -44,6 +44,7 @@ #include "oops/compiledICHolder.hpp" #include "oops/klass.inline.hpp" #include "prims/methodHandles.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/safepointMechanism.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp index e0bf06051f9..8b783a64e4d 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp @@ -44,6 +44,7 @@ #include "runtime/arguments.hpp" #include "runtime/deoptimization.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" diff --git a/src/hotspot/cpu/x86/templateTable_x86.cpp b/src/hotspot/cpu/x86/templateTable_x86.cpp index 78390405a1b..8f79af29ef4 100644 --- a/src/hotspot/cpu/x86/templateTable_x86.cpp +++ b/src/hotspot/cpu/x86/templateTable_x86.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" #include "compiler/disassembler.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/tlab_globals.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" diff --git a/src/hotspot/cpu/zero/frame_zero.cpp b/src/hotspot/cpu/zero/frame_zero.cpp index bd900de5741..70d6a5e855c 100644 --- a/src/hotspot/cpu/zero/frame_zero.cpp +++ b/src/hotspot/cpu/zero/frame_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -24,6 +24,7 @@ */ #include "precompiled.hpp" +#include "gc/shared/collectedHeap.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "memory/resourceArea.hpp" diff --git a/src/hotspot/cpu/zero/registerMap_zero.hpp b/src/hotspot/cpu/zero/registerMap_zero.hpp index 1110b68b165..b7a22a376a5 100644 --- a/src/hotspot/cpu/zero/registerMap_zero.hpp +++ b/src/hotspot/cpu/zero/registerMap_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,10 @@ // Since there is none, we just return NULL. address pd_location(VMReg reg) const { return NULL; } + address pd_location(VMReg base_reg, int slot_idx) const { + return location(base_reg->next(slot_idx)); + } + // no PD state to clear or copy: void pd_clear() {} void pd_initialize() {} diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index a976e4f6b94..92ab7dae99b 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -29,7 +29,6 @@ // no precompiled headers #include "jvm.h" -#include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 627b995dfed..a11ceac93c1 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -24,7 +24,6 @@ // no precompiled headers #include "jvm.h" -#include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 32b6bcb23f4..3b9556d688d 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2195,29 +2195,35 @@ void os::Linux::print_process_memory_info(outputStream* st) { int num_found = 0; FILE* f = ::fopen("/proc/self/status", "r"); char buf[256]; - while (::fgets(buf, sizeof(buf), f) != NULL && num_found < num_values) { - if ( (vmsize == -1 && sscanf(buf, "VmSize: " SSIZE_FORMAT " kB", &vmsize) == 1) || - (vmpeak == -1 && sscanf(buf, "VmPeak: " SSIZE_FORMAT " kB", &vmpeak) == 1) || - (vmswap == -1 && sscanf(buf, "VmSwap: " SSIZE_FORMAT " kB", &vmswap) == 1) || - (vmhwm == -1 && sscanf(buf, "VmHWM: " SSIZE_FORMAT " kB", &vmhwm) == 1) || - (vmrss == -1 && sscanf(buf, "VmRSS: " SSIZE_FORMAT " kB", &vmrss) == 1) || - (rssanon == -1 && sscanf(buf, "RssAnon: " SSIZE_FORMAT " kB", &rssanon) == 1) || - (rssfile == -1 && sscanf(buf, "RssFile: " SSIZE_FORMAT " kB", &rssfile) == 1) || - (rssshmem == -1 && sscanf(buf, "RssShmem: " SSIZE_FORMAT " kB", &rssshmem) == 1) - ) - { - num_found ++; + if (f != NULL) { + while (::fgets(buf, sizeof(buf), f) != NULL && num_found < num_values) { + if ( (vmsize == -1 && sscanf(buf, "VmSize: " SSIZE_FORMAT " kB", &vmsize) == 1) || + (vmpeak == -1 && sscanf(buf, "VmPeak: " SSIZE_FORMAT " kB", &vmpeak) == 1) || + (vmswap == -1 && sscanf(buf, "VmSwap: " SSIZE_FORMAT " kB", &vmswap) == 1) || + (vmhwm == -1 && sscanf(buf, "VmHWM: " SSIZE_FORMAT " kB", &vmhwm) == 1) || + (vmrss == -1 && sscanf(buf, "VmRSS: " SSIZE_FORMAT " kB", &vmrss) == 1) || + (rssanon == -1 && sscanf(buf, "RssAnon: " SSIZE_FORMAT " kB", &rssanon) == 1) || + (rssfile == -1 && sscanf(buf, "RssFile: " SSIZE_FORMAT " kB", &rssfile) == 1) || + (rssshmem == -1 && sscanf(buf, "RssShmem: " SSIZE_FORMAT " kB", &rssshmem) == 1) + ) + { + num_found ++; + } } - } - st->print_cr("Virtual Size: " SSIZE_FORMAT "K (peak: " SSIZE_FORMAT "K)", vmsize, vmpeak); - st->print("Resident Set Size: " SSIZE_FORMAT "K (peak: " SSIZE_FORMAT "K)", vmrss, vmhwm); - if (rssanon != -1) { // requires kernel >= 4.5 - st->print(" (anon: " SSIZE_FORMAT "K, file: " SSIZE_FORMAT "K, shmem: " SSIZE_FORMAT "K)", - rssanon, rssfile, rssshmem); - } - st->cr(); - if (vmswap != -1) { // requires kernel >= 2.6.34 - st->print_cr("Swapped out: " SSIZE_FORMAT "K", vmswap); + fclose(f); + + st->print_cr("Virtual Size: " SSIZE_FORMAT "K (peak: " SSIZE_FORMAT "K)", vmsize, vmpeak); + st->print("Resident Set Size: " SSIZE_FORMAT "K (peak: " SSIZE_FORMAT "K)", vmrss, vmhwm); + if (rssanon != -1) { // requires kernel >= 4.5 + st->print(" (anon: " SSIZE_FORMAT "K, file: " SSIZE_FORMAT "K, shmem: " SSIZE_FORMAT "K)", + rssanon, rssfile, rssshmem); + } + st->cr(); + if (vmswap != -1) { // requires kernel >= 2.6.34 + st->print_cr("Swapped out: " SSIZE_FORMAT "K", vmswap); + } + } else { + st->print_cr("Could not open /proc/self/status to get process memory related information"); } // Print glibc outstanding allocations. @@ -4699,19 +4705,46 @@ int os::active_processor_count() { return active_cpus; } +static bool should_warn_invalid_processor_id() { + if (os::processor_count() == 1) { + // Don't warn if we only have one processor + return false; + } + + static volatile int warn_once = 1; + + if (Atomic::load(&warn_once) == 0 || + Atomic::xchg(&warn_once, 0) == 0) { + // Don't warn more than once + return false; + } + + return true; +} + uint os::processor_id() { const int id = Linux::sched_getcpu(); -#ifndef PRODUCT - if (UseDebuggerErgo1 && id >= _processor_count) { - // Some debuggers limit the processor count without limiting - // the returned processor ids. Fake the processor id. - return 0; + if (id < processor_count()) { + return (uint)id; } -#endif - assert(id >= 0 && id < _processor_count, "Invalid processor id [%d]", id); - return (uint)id; + // Some environments (e.g. openvz containers and the rr debugger) incorrectly + // report a processor id that is higher than the number of processors available. + // This is problematic, for example, when implementing CPU-local data structures, + // where the processor id is used to index into an array of length processor_count(). + // If this happens we return 0 here. This is is safe since we always have at least + // one processor, but it's not optimal for performance if we're actually executing + // in an environment with more than one processor. + if (should_warn_invalid_processor_id()) { + log_warning(os)("Invalid processor id reported by the operating system " + "(got processor id %d, valid processor id range is 0-%d)", + id, processor_count() - 1); + log_warning(os)("Falling back to assuming processor id is 0. " + "This could have a negative impact on performance."); + } + + return 0; } void os::set_native_thread_name(const char *name) { diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 53dd2d99f15..15ce223bd37 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -27,7 +27,6 @@ // no precompiled headers #include "jvm.h" -#include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" #include "code/icBuffer.hpp" diff --git a/src/hotspot/os/windows/perfMemory_windows.cpp b/src/hotspot/os/windows/perfMemory_windows.cpp index 2e29f8af2b9..6db33729040 100644 --- a/src/hotspot/os/windows/perfMemory_windows.cpp +++ b/src/hotspot/os/windows/perfMemory_windows.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ #include "runtime/perfMemory.hpp" #include "services/memTracker.hpp" #include "utilities/exceptions.hpp" +#include "utilities/formatBuffer.hpp" #include #include diff --git a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp index 07f1f8be755..d3482e32f21 100644 --- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp +++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp @@ -27,7 +27,6 @@ #include "jvm.h" #include "assembler_ppc.hpp" #include "asm/assembler.inline.hpp" -#include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" #include "code/icBuffer.hpp" diff --git a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp index d1462df5fce..e7252b5653e 100644 --- a/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp +++ b/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp @@ -25,7 +25,6 @@ // no precompiled headers #include "jvm.h" #include "asm/macroAssembler.hpp" -#include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" #include "code/icBuffer.hpp" @@ -64,7 +63,6 @@ # include # include # include -# include # include # include # include @@ -391,16 +389,6 @@ enum { bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, ucontext_t* uc, JavaThread* thread) { - -/* - NOTE: does not seem to work on bsd. - if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) { - // can't decode this kind of signal - info = NULL; - } else { - assert(sig == info->si_signo, "bad siginfo"); - } -*/ // decide if this trap can be handled by a stub address stub = NULL; diff --git a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp index 8bca69035b7..18125f1c16c 100644 --- a/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp +++ b/src/hotspot/os_cpu/bsd_zero/os_bsd_zero.cpp @@ -31,7 +31,6 @@ // no precompiled headers #include "jvm.h" #include "assembler_zero.inline.hpp" -#include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" diff --git a/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.S b/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.S new file mode 100644 index 00000000000..72969b1df63 --- /dev/null +++ b/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.S @@ -0,0 +1,96 @@ +// Copyright (c) 2021, Red Hat Inc. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. + + + + .text + + .globl aarch64_atomic_fetch_add_8_default_impl + .align 5 +aarch64_atomic_fetch_add_8_default_impl: +0: ldaxr x2, [x0] + add x8, x2, x1 + stlxr w9, x8, [x0] + cbnz w9, 0b + mov x0, x2 + ret + + .globl aarch64_atomic_fetch_add_4_default_impl + .align 5 +aarch64_atomic_fetch_add_4_default_impl: +0: ldaxr w2, [x0] + add w8, w2, w1 + stlxr w9, w8, [x0] + cbnz w9, 0b + mov w0, w2 + ret + + .globl aarch64_atomic_xchg_4_default_impl + .align 5 +aarch64_atomic_xchg_4_default_impl: +0: ldaxr w2, [x0] + stlxr w8, w1, [x0] + cbnz w8, 0b + mov w0, w2 + ret + + .globl aarch64_atomic_xchg_8_default_impl + .align 5 +aarch64_atomic_xchg_8_default_impl: +0: ldaxr x2, [x0] + stlxr w8, x1, [x0] + cbnz w8, 0b + mov x0, x2 + ret + + .globl aarch64_atomic_cmpxchg_1_default_impl + .align 5 +aarch64_atomic_cmpxchg_1_default_impl: +0: ldxrb w3, [x0] + eor w8, w3, w1 + tst x8, #0xff + b.ne 1f + stxrb w8, w2, [x0] + cbnz w8, 0b +1: mov w0, w3 + ret + + .globl aarch64_atomic_cmpxchg_4_default_impl + .align 5 +aarch64_atomic_cmpxchg_4_default_impl: +0: ldxr w3, [x0] + cmp w3, w1 + b.ne 1f + stxr w8, w2, [x0] + cbnz w8, 0b +1: mov w0, w3 + ret + + .globl aarch64_atomic_cmpxchg_8_default_impl + .align 5 +aarch64_atomic_cmpxchg_8_default_impl: +0: ldxr x3, [x0] + cmp x3, x1 + b.ne 1f + stxr w8, x2, [x0] + cbnz w8, 0b +1: mov x0, x3 + ret diff --git a/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp b/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp index 8e275a4173e..2767e33049e 100644 --- a/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp +++ b/src/hotspot/os_cpu/linux_aarch64/atomic_linux_aarch64.hpp @@ -1,6 +1,6 @@ /* * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, 2019, Red Hat Inc. All rights reserved. + * Copyright (c) 2014, 2021, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,58 +26,166 @@ #ifndef OS_CPU_LINUX_AARCH64_ATOMIC_LINUX_AARCH64_HPP #define OS_CPU_LINUX_AARCH64_ATOMIC_LINUX_AARCH64_HPP +#include "atomic_aarch64.hpp" #include "runtime/vm_version.hpp" // Implementation of class atomic + // Note that memory_order_conservative requires a full barrier after atomic stores. // See https://patchwork.kernel.org/patch/3575821/ +// Call one of the stubs from C++. This uses the C calling convention, +// but this asm definition is used in order only to clobber the +// registers we use. If we called the stubs via an ABI call we'd have +// to save X0 - X18 and most of the vectors. +// +// This really ought to be a template definition, but see GCC Bug +// 33661, template methods forget explicit local register asm +// vars. The problem is that register specifiers attached to local +// variables are ignored in any template function. +inline uint64_t bare_atomic_fastcall(address stub, volatile void *ptr, uint64_t arg1, uint64_t arg2 = 0) { + register uint64_t reg0 __asm__("x0") = (uint64_t)ptr; + register uint64_t reg1 __asm__("x1") = arg1; + register uint64_t reg2 __asm__("x2") = arg2; + register uint64_t reg3 __asm__("x3") = (uint64_t)stub; + register uint64_t result __asm__("x0"); + asm volatile(// "stp x29, x30, [sp, #-16]!;" + " blr %1;" + // " ldp x29, x30, [sp], #16 // regs %0, %1, %2, %3, %4" + : "=r"(result), "+r"(reg3), "+r"(reg2) + : "r"(reg1), "0"(reg0) : "x8", "x9", "x30", "cc", "memory"); + return result; +} + +template +inline D atomic_fastcall(F stub, volatile D *dest, T1 arg1) { + return (D)bare_atomic_fastcall(CAST_FROM_FN_PTR(address, stub), + dest, (uint64_t)arg1); +} + +template +inline D atomic_fastcall(F stub, volatile D *dest, T1 arg1, T2 arg2) { + return (D)bare_atomic_fastcall(CAST_FROM_FN_PTR(address, stub), + dest, (uint64_t)arg1, (uint64_t)arg2); +} + template struct Atomic::PlatformAdd { template - D add_and_fetch(D volatile* dest, I add_value, atomic_memory_order order) const { - D res = __atomic_add_fetch(dest, add_value, __ATOMIC_RELEASE); - FULL_MEM_BARRIER; - return res; - } + D fetch_and_add(D volatile* dest, I add_value, atomic_memory_order order) const; template - D fetch_and_add(D volatile* dest, I add_value, atomic_memory_order order) const { - return add_and_fetch(dest, add_value, order) - add_value; + D add_and_fetch(D volatile* dest, I add_value, atomic_memory_order order) const { + D value = fetch_and_add(dest, add_value, order) + add_value; + return value; } }; -template +template<> +template +inline D Atomic::PlatformAdd<4>::fetch_and_add(D volatile* dest, I add_value, + atomic_memory_order order) const { + STATIC_ASSERT(4 == sizeof(I)); + STATIC_ASSERT(4 == sizeof(D)); + D old_value + = atomic_fastcall(aarch64_atomic_fetch_add_4_impl, dest, add_value); + FULL_MEM_BARRIER; + return old_value; +} + +template<> +template +inline D Atomic::PlatformAdd<8>::fetch_and_add(D volatile* dest, I add_value, + atomic_memory_order order) const { + STATIC_ASSERT(8 == sizeof(I)); + STATIC_ASSERT(8 == sizeof(D)); + D old_value + = atomic_fastcall(aarch64_atomic_fetch_add_8_impl, dest, add_value); + FULL_MEM_BARRIER; + return old_value; +} + +template<> template -inline T Atomic::PlatformXchg::operator()(T volatile* dest, - T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(byte_size == sizeof(T)); - T res = __atomic_exchange_n(dest, exchange_value, __ATOMIC_RELEASE); +inline T Atomic::PlatformXchg<4>::operator()(T volatile* dest, + T exchange_value, + atomic_memory_order order) const { + STATIC_ASSERT(4 == sizeof(T)); + T old_value = atomic_fastcall(aarch64_atomic_xchg_4_impl, dest, exchange_value); FULL_MEM_BARRIER; - return res; + return old_value; } -// __attribute__((unused)) on dest is to get rid of spurious GCC warnings. -template +template<> +template +inline T Atomic::PlatformXchg<8>::operator()(T volatile* dest, T exchange_value, + atomic_memory_order order) const { + STATIC_ASSERT(8 == sizeof(T)); + T old_value = atomic_fastcall(aarch64_atomic_xchg_8_impl, dest, exchange_value); + FULL_MEM_BARRIER; + return old_value; +} + +template<> template -inline T Atomic::PlatformCmpxchg::operator()(T volatile* dest __attribute__((unused)), - T compare_value, - T exchange_value, - atomic_memory_order order) const { - STATIC_ASSERT(byte_size == sizeof(T)); +inline T Atomic::PlatformCmpxchg<1>::operator()(T volatile* dest, + T compare_value, + T exchange_value, + atomic_memory_order order) const { + STATIC_ASSERT(1 == sizeof(T)); + aarch64_atomic_stub_t stub = aarch64_atomic_cmpxchg_1_impl; if (order == memory_order_relaxed) { - T value = compare_value; - __atomic_compare_exchange(dest, &value, &exchange_value, /*weak*/false, - __ATOMIC_RELAXED, __ATOMIC_RELAXED); - return value; + T old_value = atomic_fastcall(stub, dest, + compare_value, exchange_value); + return old_value; } else { - T value = compare_value; FULL_MEM_BARRIER; - __atomic_compare_exchange(dest, &value, &exchange_value, /*weak*/false, - __ATOMIC_RELAXED, __ATOMIC_RELAXED); + T old_value = atomic_fastcall(stub, dest, + compare_value, exchange_value); FULL_MEM_BARRIER; - return value; + return old_value; + } +} + +template<> +template +inline T Atomic::PlatformCmpxchg<4>::operator()(T volatile* dest, + T compare_value, + T exchange_value, + atomic_memory_order order) const { + STATIC_ASSERT(4 == sizeof(T)); + aarch64_atomic_stub_t stub = aarch64_atomic_cmpxchg_4_impl; + if (order == memory_order_relaxed) { + T old_value = atomic_fastcall(stub, dest, + compare_value, exchange_value); + return old_value; + } else { + FULL_MEM_BARRIER; + T old_value = atomic_fastcall(stub, dest, + compare_value, exchange_value); + FULL_MEM_BARRIER; + return old_value; + } +} + +template<> +template +inline T Atomic::PlatformCmpxchg<8>::operator()(T volatile* dest, + T compare_value, + T exchange_value, + atomic_memory_order order) const { + STATIC_ASSERT(8 == sizeof(T)); + aarch64_atomic_stub_t stub = aarch64_atomic_cmpxchg_8_impl; + if (order == memory_order_relaxed) { + T old_value = atomic_fastcall(stub, dest, + compare_value, exchange_value); + return old_value; + } else { + FULL_MEM_BARRIER; + T old_value = atomic_fastcall(stub, dest, + compare_value, exchange_value); + FULL_MEM_BARRIER; + return old_value; } } diff --git a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp index a785369a8dd..13702ba1c23 100644 --- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp @@ -26,7 +26,6 @@ // no precompiled headers #include "jvm.h" #include "asm/macroAssembler.hpp" -#include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" #include "code/icBuffer.hpp" diff --git a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp index 12eb0f543ce..064c1fba16b 100644 --- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp +++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp @@ -25,7 +25,6 @@ // no precompiled headers #include "jvm.h" #include "assembler_arm.inline.hpp" -#include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" diff --git a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp index 0e390ab3f28..5edb303b68b 100644 --- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp +++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp @@ -27,7 +27,6 @@ #include "jvm.h" #include "assembler_ppc.hpp" #include "asm/assembler.inline.hpp" -#include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" #include "code/icBuffer.hpp" diff --git a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp index cd370d2f7a3..53b017d2217 100644 --- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp +++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp @@ -28,7 +28,6 @@ // no precompiled headers #include "jvm.h" #include "asm/assembler.inline.hpp" -#include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/icBuffer.hpp" #include "code/nativeInst.hpp" diff --git a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp index ed603aa641e..dcd2f566a16 100644 --- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp +++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp @@ -25,7 +25,6 @@ // no precompiled headers #include "jvm.h" #include "asm/macroAssembler.hpp" -#include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" #include "code/icBuffer.hpp" diff --git a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp index e38b7d351ae..ac57da78a25 100644 --- a/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp +++ b/src/hotspot/os_cpu/linux_zero/os_linux_zero.cpp @@ -26,7 +26,6 @@ // no precompiled headers #include "jvm.h" #include "assembler_zero.inline.hpp" -#include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" diff --git a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp index 6422eb406e0..94a96fc05af 100644 --- a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp +++ b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.cpp @@ -25,7 +25,6 @@ #include "precompiled.hpp" #include "jvm.h" #include "asm/macroAssembler.hpp" -#include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" #include "code/icBuffer.hpp" diff --git a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp index 2e18762cf63..764780db4e1 100644 --- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp @@ -25,7 +25,6 @@ // no precompiled headers #include "jvm.h" #include "asm/macroAssembler.hpp" -#include "classfile/classLoader.hpp" #include "classfile/vmSymbols.hpp" #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp index af42bb92b53..7d76c8ae751 100644 --- a/src/hotspot/share/asm/codeBuffer.cpp +++ b/src/hotspot/share/asm/codeBuffer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ #include "asm/codeBuffer.hpp" #include "code/oopRecorder.inline.hpp" #include "compiler/disassembler.hpp" +#include "logging/log.hpp" +#include "oops/klass.inline.hpp" #include "oops/methodData.hpp" #include "oops/oop.inline.hpp" #include "runtime/icache.hpp" diff --git a/src/hotspot/share/c1/c1_Instruction.cpp b/src/hotspot/share/c1/c1_Instruction.cpp index bafaf6140b7..43bc726e788 100644 --- a/src/hotspot/share/c1/c1_Instruction.cpp +++ b/src/hotspot/share/c1/c1_Instruction.cpp @@ -238,7 +238,7 @@ ciType* Constant::exact_type() const { ciType* LoadIndexed::exact_type() const { ciType* array_type = array()->exact_type(); - if (delayed() != NULL && array_type != NULL) { + if (delayed() == NULL && array_type != NULL) { assert(array_type->is_array_klass(), "what else?"); ciArrayKlass* ak = (ciArrayKlass*)array_type; diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index 7e1276321ee..7c7557ba5b8 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -3050,6 +3050,11 @@ ciKlass* LIRGenerator::profile_type(ciMethodData* md, int md_base_offset, int md do_update = exact_klass == NULL || ciTypeEntries::valid_ciklass(profiled_k) != exact_klass; } + // Inline types can't be null + if (exact_klass != NULL && exact_klass->is_inlinetype()) { + do_null = false; + } + if (!do_null && !do_update) { return result; } diff --git a/src/hotspot/share/ci/ciBaseObject.hpp b/src/hotspot/share/ci/ciBaseObject.hpp index 00b842156c4..9c204cb70ed 100644 --- a/src/hotspot/share/ci/ciBaseObject.hpp +++ b/src/hotspot/share/ci/ciBaseObject.hpp @@ -27,7 +27,6 @@ #include "ci/ciClassList.hpp" #include "memory/allocation.hpp" -#include "runtime/jniHandles.hpp" // ciBaseObject // diff --git a/src/hotspot/share/ci/ciEnv.hpp b/src/hotspot/share/ci/ciEnv.hpp index 1ab9a3879dc..2f7b45ec745 100644 --- a/src/hotspot/share/ci/ciEnv.hpp +++ b/src/hotspot/share/ci/ciEnv.hpp @@ -31,6 +31,7 @@ #include "code/debugInfoRec.hpp" #include "code/dependencies.hpp" #include "code/exceptionHandlerTable.hpp" +#include "compiler/compilerThread.hpp" #include "compiler/oopMap.hpp" #include "oops/methodData.hpp" #include "runtime/thread.hpp" diff --git a/src/hotspot/share/ci/ciKlass.cpp b/src/hotspot/share/ci/ciKlass.cpp index c78a761bad5..af597709032 100644 --- a/src/hotspot/share/ci/ciKlass.cpp +++ b/src/hotspot/share/ci/ciKlass.cpp @@ -207,6 +207,15 @@ jint ciKlass::access_flags() { ) } +// ------------------------------------------------------------------ +// ciKlass::prototype_header +markWord ciKlass::prototype_header() const { + assert(is_loaded(), "not loaded"); + GUARDED_VM_ENTRY( + return get_Klass()->prototype_header(); + ) +} + // ------------------------------------------------------------------ // ciKlass::print_impl // diff --git a/src/hotspot/share/ci/ciKlass.hpp b/src/hotspot/share/ci/ciKlass.hpp index 544be65d2cd..0a6a9228f53 100644 --- a/src/hotspot/share/ci/ciKlass.hpp +++ b/src/hotspot/share/ci/ciKlass.hpp @@ -130,6 +130,8 @@ class ciKlass : public ciType { // Fetch Klass::access_flags. jint access_flags(); + markWord prototype_header() const; + // What kind of ciObject is this? bool is_klass() const { return true; } diff --git a/src/hotspot/share/ci/ciMetadata.cpp b/src/hotspot/share/ci/ciMetadata.cpp index 9bffeadf9e8..f0d1fcf4357 100644 --- a/src/hotspot/share/ci/ciMetadata.cpp +++ b/src/hotspot/share/ci/ciMetadata.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,9 @@ #include "ci/ciUtilities.inline.hpp" #include "gc/shared/collectedHeap.inline.hpp" +// Not inlined to preserve visibility of ciMetaData vtable symbol. Required by SA. +bool ciMetadata::is_classless() const { return false; } + // ------------------------------------------------------------------ // ciMetadata::print // diff --git a/src/hotspot/share/ci/ciMetadata.hpp b/src/hotspot/share/ci/ciMetadata.hpp index 9e992bb99e2..dd4a8cce6c9 100644 --- a/src/hotspot/share/ci/ciMetadata.hpp +++ b/src/hotspot/share/ci/ciMetadata.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ #include "ci/ciBaseObject.hpp" #include "ci/ciClassList.hpp" #include "runtime/handles.hpp" -#include "runtime/jniHandles.hpp" // ciMetadata // @@ -44,7 +43,7 @@ class ciMetadata: public ciBaseObject { ciMetadata(): _metadata(NULL) {} ciMetadata(Metadata* o): _metadata(o) {} - virtual bool is_classless() const { return false; } + virtual bool is_classless() const; public: bool is_loaded() const { return _metadata != NULL || is_classless(); } diff --git a/src/hotspot/share/ci/ciMethodData.cpp b/src/hotspot/share/ci/ciMethodData.cpp index f41a5d54d83..decd6a0dda9 100644 --- a/src/hotspot/share/ci/ciMethodData.cpp +++ b/src/hotspot/share/ci/ciMethodData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ #include "compiler/compiler_globals.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" +#include "oops/klass.inline.hpp" #include "runtime/deoptimization.hpp" #include "utilities/copy.hpp" diff --git a/src/hotspot/share/ci/ciObject.hpp b/src/hotspot/share/ci/ciObject.hpp index 8e3ffe64ef5..0587df338c5 100644 --- a/src/hotspot/share/ci/ciObject.hpp +++ b/src/hotspot/share/ci/ciObject.hpp @@ -28,7 +28,6 @@ #include "ci/ciBaseObject.hpp" #include "ci/ciClassList.hpp" #include "runtime/handles.hpp" -#include "runtime/jniHandles.hpp" // ciObject // diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index 00a84fa596a..c00a3e11014 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -79,6 +79,7 @@ #include "utilities/align.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/copy.hpp" +#include "utilities/formatBuffer.hpp" #include "utilities/exceptions.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/growableArray.hpp" diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index 6763871581b..8c6c9d58851 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -287,7 +287,7 @@ ClassPathZipEntry::~ClassPathZipEntry() { u1* ClassPathZipEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) { // enable call to C land - JavaThread* thread = JavaThread::current(); + JavaThread* thread = THREAD->as_Java_thread(); ThreadToNativeFromVM ttn(thread); // check whether zip archive contains name jint name_len; @@ -501,7 +501,7 @@ void ClassLoader::trace_class_path(const char* msg, const char* name) { } } -void ClassLoader::setup_bootstrap_search_path() { +void ClassLoader::setup_bootstrap_search_path(TRAPS) { const char* sys_class_path = Arguments::get_sysclasspath(); assert(sys_class_path != NULL, "System boot class path must not be NULL"); if (PrintSharedArchiveAndExit) { @@ -510,11 +510,11 @@ void ClassLoader::setup_bootstrap_search_path() { } else { trace_class_path("bootstrap loader class path=", sys_class_path); } - setup_boot_search_path(sys_class_path); + setup_bootstrap_search_path_impl(sys_class_path, CHECK); } #if INCLUDE_CDS -void ClassLoader::setup_app_search_path(const char *class_path) { +void ClassLoader::setup_app_search_path(const char *class_path, TRAPS) { Arguments::assert_is_dumping_archive(); ResourceMark rm; @@ -522,7 +522,7 @@ void ClassLoader::setup_app_search_path(const char *class_path) { while (cp_stream.has_next()) { const char* path = cp_stream.get_next(); - update_class_path_entry_list(path, false, false, false); + update_class_path_entry_list(path, false, false, false, CHECK); } } @@ -542,7 +542,7 @@ void ClassLoader::add_to_module_path_entries(const char* path, } // Add a module path to the _module_path_entries list. -void ClassLoader::update_module_path_entry_list(const char *path, TRAPS) { +void ClassLoader::setup_module_search_path(const char* path, TRAPS) { Arguments::assert_is_dumping_archive(); struct stat st; if (os::stat(path, &st) != 0) { @@ -562,10 +562,6 @@ void ClassLoader::update_module_path_entry_list(const char *path, TRAPS) { return; } -void ClassLoader::setup_module_search_path(const char* path, TRAPS) { - update_module_path_entry_list(path, THREAD); -} - #endif // INCLUDE_CDS void ClassLoader::close_jrt_image() { @@ -632,8 +628,7 @@ bool ClassLoader::is_in_patch_mod_entries(Symbol* module_name) { } // Set up the _jrt_entry if present and boot append path -void ClassLoader::setup_boot_search_path(const char *class_path) { - EXCEPTION_MARK; +void ClassLoader::setup_bootstrap_search_path_impl(const char *class_path, TRAPS) { ResourceMark rm(THREAD); ClasspathStream cp_stream(class_path); bool set_base_piece = true; @@ -675,7 +670,7 @@ void ClassLoader::setup_boot_search_path(const char *class_path) { } else { // Every entry on the system boot class path after the initial base piece, // which is set by os::set_boot_path(), is considered an appended entry. - update_class_path_entry_list(path, false, true, false); + update_class_path_entry_list(path, false, true, false, CHECK); } } } @@ -722,7 +717,7 @@ ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const str bool is_boot_append, bool from_class_path_attr, TRAPS) { - JavaThread* thread = JavaThread::current(); + JavaThread* thread = THREAD->as_Java_thread(); ClassPathEntry* new_entry = NULL; if ((st->st_mode & S_IFMT) == S_IFREG) { ResourceMark rm(thread); @@ -847,7 +842,8 @@ void ClassLoader::add_to_boot_append_entries(ClassPathEntry *new_entry) { // jdk/internal/loader/ClassLoaders$AppClassLoader instance. void ClassLoader::add_to_app_classpath_entries(const char* path, ClassPathEntry* entry, - bool check_for_duplicates) { + bool check_for_duplicates, + TRAPS) { #if INCLUDE_CDS assert(entry != NULL, "ClassPathEntry should not be NULL"); ClassPathEntry* e = _app_classpath_entries; @@ -871,7 +867,7 @@ void ClassLoader::add_to_app_classpath_entries(const char* path, } if (entry->is_jar_file()) { - ClassLoaderExt::process_jar_manifest(entry, check_for_duplicates); + ClassLoaderExt::process_jar_manifest(entry, check_for_duplicates, CHECK); } #endif } @@ -881,13 +877,12 @@ bool ClassLoader::update_class_path_entry_list(const char *path, bool check_for_duplicates, bool is_boot_append, bool from_class_path_attr, - bool throw_exception) { + TRAPS) { struct stat st; if (os::stat(path, &st) == 0) { // File or directory found ClassPathEntry* new_entry = NULL; - Thread* THREAD = Thread::current(); - new_entry = create_class_path_entry(path, &st, throw_exception, is_boot_append, from_class_path_attr, CHECK_(false)); + new_entry = create_class_path_entry(path, &st, /*throw_exception=*/true, is_boot_append, from_class_path_attr, CHECK_false); if (new_entry == NULL) { return false; } @@ -897,7 +892,7 @@ bool ClassLoader::update_class_path_entry_list(const char *path, if (is_boot_append) { add_to_boot_append_entries(new_entry); } else { - add_to_app_classpath_entries(path, new_entry, check_for_duplicates); + add_to_app_classpath_entries(path, new_entry, check_for_duplicates, CHECK_false); } return true; } else { @@ -1286,7 +1281,7 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR return NULL; } - result->set_classpath_index(classpath_index, THREAD); + result->set_classpath_index(classpath_index); return result; } @@ -1421,7 +1416,7 @@ void ClassLoader::record_result(InstanceKlass* ik, const ClassFileStream* stream ik->name()->utf8_length()); assert(file_name != NULL, "invariant"); - ClassLoaderExt::record_result(classpath_index, ik, THREAD); + ClassLoaderExt::record_result(classpath_index, ik, CHECK); } #endif // INCLUDE_CDS @@ -1430,9 +1425,7 @@ void ClassLoader::record_result(InstanceKlass* ik, const ClassFileStream* stream // this list has been created, it must not change order (see class PackageInfo) // it can be appended to and is by jvmti. -void ClassLoader::initialize() { - EXCEPTION_MARK; - +void ClassLoader::initialize(TRAPS) { if (UsePerfData) { // jvmstat performance counters NEWPERFTICKCOUNTER(_perf_accumulated_time, SUN_CLS, "time"); @@ -1464,7 +1457,7 @@ void ClassLoader::initialize() { // lookup java library entry points load_java_library(); // jimage library entry points are loaded below, in lookup_vm_options - setup_bootstrap_search_path(); + setup_bootstrap_search_path(CHECK); } char* lookup_vm_resource(JImageFile *jimage, const char *jimage_version, const char *path) { @@ -1501,16 +1494,16 @@ char* ClassLoader::lookup_vm_options() { } #if INCLUDE_CDS -void ClassLoader::initialize_shared_path() { +void ClassLoader::initialize_shared_path(TRAPS) { if (Arguments::is_dumping_archive()) { - ClassLoaderExt::setup_search_paths(); + ClassLoaderExt::setup_search_paths(CHECK); } } void ClassLoader::initialize_module_path(TRAPS) { if (Arguments::is_dumping_archive()) { - ClassLoaderExt::setup_module_paths(THREAD); - FileMapInfo::allocate_shared_path_table(); + ClassLoaderExt::setup_module_paths(CHECK); + FileMapInfo::allocate_shared_path_table(CHECK); } } @@ -1566,7 +1559,11 @@ int ClassLoader::compute_Object_vtable() { void classLoader_init1() { - ClassLoader::initialize(); + EXCEPTION_MARK; + ClassLoader::initialize(THREAD); + if (HAS_PENDING_EXCEPTION) { + vm_exit_during_initialization("ClassLoader::initialize() failed unexpectedly"); + } } // Complete the ClassPathEntry setup for the boot loader diff --git a/src/hotspot/share/classfile/classLoader.hpp b/src/hotspot/share/classfile/classLoader.hpp index 8df5a50b735..da057b54edb 100644 --- a/src/hotspot/share/classfile/classLoader.hpp +++ b/src/hotspot/share/classfile/classLoader.hpp @@ -222,11 +222,12 @@ class ClassLoader: AllStatic { CDS_ONLY(static ClassPathEntry* _last_app_classpath_entry;) CDS_ONLY(static ClassPathEntry* _module_path_entries;) CDS_ONLY(static ClassPathEntry* _last_module_path_entry;) - CDS_ONLY(static void setup_app_search_path(const char* class_path);) + CDS_ONLY(static void setup_app_search_path(const char* class_path, TRAPS);) CDS_ONLY(static void setup_module_search_path(const char* path, TRAPS);) static void add_to_app_classpath_entries(const char* path, ClassPathEntry* entry, - bool check_for_duplicates); + bool check_for_duplicates, + TRAPS); CDS_ONLY(static void add_to_module_path_entries(const char* path, ClassPathEntry* entry);) public: @@ -240,8 +241,8 @@ class ClassLoader: AllStatic { // - setup the boot loader's system class path // - setup the boot loader's patch mod entries, if present // - create the ModuleEntry for java.base - static void setup_bootstrap_search_path(); - static void setup_boot_search_path(const char *class_path); + static void setup_bootstrap_search_path(TRAPS); + static void setup_bootstrap_search_path_impl(const char *class_path, TRAPS); static void setup_patch_mod_entries(); static void create_javabase(); @@ -272,8 +273,7 @@ class ClassLoader: AllStatic { bool check_for_duplicates, bool is_boot_append, bool from_class_path_attr, - bool throw_exception=true); - CDS_ONLY(static void update_module_path_entry_list(const char *path, TRAPS);) + TRAPS); static void print_bootclasspath(); // Timing @@ -335,9 +335,9 @@ class ClassLoader: AllStatic { static objArrayOop get_system_packages(TRAPS); // Initialization - static void initialize(); + static void initialize(TRAPS); static void classLoader_init2(TRAPS); - CDS_ONLY(static void initialize_shared_path();) + CDS_ONLY(static void initialize_shared_path(TRAPS);) CDS_ONLY(static void initialize_module_path(TRAPS);) static int compute_Object_vtable(); diff --git a/src/hotspot/share/classfile/classLoaderExt.cpp b/src/hotspot/share/classfile/classLoaderExt.cpp index 8709498b56c..f9003f34368 100644 --- a/src/hotspot/share/classfile/classLoaderExt.cpp +++ b/src/hotspot/share/classfile/classLoaderExt.cpp @@ -34,6 +34,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/systemDictionaryShared.hpp" #include "classfile/vmSymbols.hpp" +#include "gc/shared/collectedHeap.hpp" #include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" @@ -64,7 +65,7 @@ void ClassLoaderExt::append_boot_classpath(ClassPathEntry* new_entry) { ClassLoader::add_to_boot_append_entries(new_entry); } -void ClassLoaderExt::setup_app_search_path() { +void ClassLoaderExt::setup_app_search_path(TRAPS) { Arguments::assert_is_dumping_archive(); _app_class_paths_start_index = ClassLoader::num_boot_classpath_entries(); char* app_class_path = os::strdup(Arguments::get_appclasspath()); @@ -76,7 +77,7 @@ void ClassLoaderExt::setup_app_search_path() { trace_class_path("app loader class path (skipped)=", app_class_path); } else { trace_class_path("app loader class path=", app_class_path); - ClassLoader::setup_app_search_path(app_class_path); + ClassLoader::setup_app_search_path(app_class_path, CHECK); } } @@ -87,7 +88,7 @@ void ClassLoaderExt::process_module_table(ModuleEntryTable* met, TRAPS) { char* path = m->location()->as_C_string(); if (strncmp(path, "file:", 5) == 0) { path = ClassLoader::skip_uri_protocol(path); - ClassLoader::setup_module_search_path(path, THREAD); + ClassLoader::setup_module_search_path(path, CHECK); } m = m->next(); } @@ -99,7 +100,7 @@ void ClassLoaderExt::setup_module_paths(TRAPS) { ClassLoader::num_app_classpath_entries(); Handle system_class_loader (THREAD, SystemDictionary::java_system_loader()); ModuleEntryTable* met = Modules::get_module_entry_table(system_class_loader); - process_module_table(met, THREAD); + process_module_table(met, CHECK); } char* ClassLoaderExt::read_manifest(ClassPathEntry* entry, jint *manifest_size, bool clean_text, TRAPS) { @@ -163,8 +164,7 @@ char* ClassLoaderExt::get_class_path_attr(const char* jar_path, char* manifest, } void ClassLoaderExt::process_jar_manifest(ClassPathEntry* entry, - bool check_for_duplicates) { - Thread* THREAD = Thread::current(); + bool check_for_duplicates, TRAPS) { ResourceMark rm(THREAD); jint manifest_size; char* manifest = read_manifest(entry, &manifest_size, CHECK); @@ -212,7 +212,8 @@ void ClassLoaderExt::process_jar_manifest(ClassPathEntry* entry, char* libname = NEW_RESOURCE_ARRAY(char, libname_len + 1); int n = os::snprintf(libname, libname_len + 1, "%.*s%s", dir_len, dir_name, file_start); assert((size_t)n == libname_len, "Unexpected number of characters in string"); - if (ClassLoader::update_class_path_entry_list(libname, true, false, true /* from_class_path_attr */)) { + bool status = ClassLoader::update_class_path_entry_list(libname, true, false, true /* from_class_path_attr */, CHECK); + if (status) { trace_class_path("library = ", libname); } else { trace_class_path("library (non-existent) = ", libname); @@ -225,8 +226,8 @@ void ClassLoaderExt::process_jar_manifest(ClassPathEntry* entry, } } -void ClassLoaderExt::setup_search_paths() { - ClassLoaderExt::setup_app_search_path(); +void ClassLoaderExt::setup_search_paths(TRAPS) { + ClassLoaderExt::setup_app_search_path(CHECK); } void ClassLoaderExt::record_result(const s2 classpath_index, diff --git a/src/hotspot/share/classfile/classLoaderExt.hpp b/src/hotspot/share/classfile/classLoaderExt.hpp index cca5bed24f5..983741bc87b 100644 --- a/src/hotspot/share/classfile/classLoaderExt.hpp +++ b/src/hotspot/share/classfile/classLoaderExt.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ class ClassLoaderExt: public ClassLoader { // AllStatic }; static char* get_class_path_attr(const char* jar_path, char* manifest, jint manifest_size); - static void setup_app_search_path(); // Only when -Xshare:dump + static void setup_app_search_path(TRAPS); // Only when -Xshare:dump static void process_module_table(ModuleEntryTable* met, TRAPS); // index of first app JAR in shared classpath entry table static jshort _app_class_paths_start_index; @@ -61,12 +61,12 @@ class ClassLoaderExt: public ClassLoader { // AllStatic static ClassPathEntry* find_classpath_entry_from_cache(const char* path, TRAPS); public: - static void process_jar_manifest(ClassPathEntry* entry, bool check_for_duplicates); + static void process_jar_manifest(ClassPathEntry* entry, bool check_for_duplicates, TRAPS); // Called by JVMTI code to add boot classpath static void append_boot_classpath(ClassPathEntry* new_entry); - static void setup_search_paths(); + static void setup_search_paths(TRAPS); static void setup_module_paths(TRAPS); static char* read_manifest(ClassPathEntry* entry, jint *manifest_size, TRAPS) { diff --git a/src/hotspot/share/classfile/compactHashtable.cpp b/src/hotspot/share/classfile/compactHashtable.cpp index eac232a914c..808de7c7fb2 100644 --- a/src/hotspot/share/classfile/compactHashtable.cpp +++ b/src/hotspot/share/classfile/compactHashtable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,10 +27,9 @@ #include "classfile/compactHashtable.hpp" #include "classfile/javaClasses.hpp" #include "logging/logMessage.hpp" -#include "memory/dynamicArchive.hpp" +#include "memory/archiveBuilder.hpp" #include "memory/heapShared.inline.hpp" #include "memory/metadataFactory.hpp" -#include "memory/metaspaceShared.hpp" #include "runtime/arguments.hpp" #include "runtime/globals.hpp" #include "runtime/vmThread.hpp" @@ -74,11 +73,11 @@ CompactHashtableWriter::~CompactHashtableWriter() { size_t CompactHashtableWriter::estimate_size(int num_entries) { int num_buckets = calculate_num_buckets(num_entries); - size_t bucket_bytes = MetaspaceShared::ro_array_bytesize(num_buckets + 1); + size_t bucket_bytes = ArchiveBuilder::ro_array_bytesize(num_buckets + 1); // In worst case, we have no VALUE_ONLY_BUCKET_TYPE, so each entry takes 2 slots int entries_space = 2 * num_entries; - size_t entry_bytes = MetaspaceShared::ro_array_bytesize(entries_space); + size_t entry_bytes = ArchiveBuilder::ro_array_bytesize(entries_space); return bucket_bytes + entry_bytes @@ -109,8 +108,8 @@ void CompactHashtableWriter::allocate_table() { "Too many entries."); } - _compact_buckets = MetaspaceShared::new_ro_array(_num_buckets + 1); - _compact_entries = MetaspaceShared::new_ro_array(entries_space); + _compact_buckets = ArchiveBuilder::new_ro_array(_num_buckets + 1); + _compact_entries = ArchiveBuilder::new_ro_array(entries_space); _stats->bucket_count = _num_buckets; _stats->bucket_bytes = align_up(_compact_buckets->size() * BytesPerWord, @@ -198,13 +197,8 @@ void SimpleCompactHashtable::init(address base_address, u4 entry_count, u4 bucke _bucket_count = bucket_count; _entry_count = entry_count; _base_address = base_address; - if (DynamicDumpSharedSpaces) { - _buckets = DynamicArchive::buffer_to_target(buckets); - _entries = DynamicArchive::buffer_to_target(entries); - } else { - _buckets = buckets; - _entries = entries; - } + _buckets = buckets; + _entries = entries; } size_t SimpleCompactHashtable::calculate_header_size() { diff --git a/src/hotspot/share/classfile/compactHashtable.hpp b/src/hotspot/share/classfile/compactHashtable.hpp index 4b27058b59d..a5127576a8d 100644 --- a/src/hotspot/share/classfile/compactHashtable.hpp +++ b/src/hotspot/share/classfile/compactHashtable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,10 @@ class CompactHashtableStats { int hashentry_bytes; int bucket_count; int bucket_bytes; + + CompactHashtableStats() : + hashentry_count(0), hashentry_bytes(0), + bucket_count(0), bucket_bytes(0) {} }; #if INCLUDE_CDS diff --git a/src/hotspot/share/classfile/dictionary.cpp b/src/hotspot/share/classfile/dictionary.cpp index ea36526c69b..c507c79b17f 100644 --- a/src/hotspot/share/classfile/dictionary.cpp +++ b/src/hotspot/share/classfile/dictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -132,12 +132,17 @@ bool Dictionary::resize_if_needed() { return (desired_size != 0); } +bool DictionaryEntry::is_valid_protection_domain(Handle protection_domain) { + + return protection_domain() == NULL || !java_lang_System::allow_security_manager() + ? true + : contains_protection_domain(protection_domain()); +} + bool DictionaryEntry::contains_protection_domain(oop protection_domain) const { - // Lock the pd_set list. This lock cannot safepoint since the caller holds - // a Dictionary entry, which can be moved if the Dictionary is resized. - MutexLocker ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag); #ifdef ASSERT if (protection_domain == instance_klass()->protection_domain()) { + MutexLocker ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag); // Ensure this doesn't show up in the pd_set (invariant) bool in_pd_set = false; for (ProtectionDomainEntry* current = pd_set(); @@ -160,10 +165,15 @@ bool DictionaryEntry::contains_protection_domain(oop protection_domain) const { return true; } + // Lock the pd_set list. This lock cannot safepoint since the caller holds + // a Dictionary entry, which can be moved if the Dictionary is resized. + MutexLocker ml(ProtectionDomainSet_lock, Mutex::_no_safepoint_check_flag); for (ProtectionDomainEntry* current = pd_set(); current != NULL; current = current->next()) { - if (current->object_no_keepalive() == protection_domain) return true; + if (current->object_no_keepalive() == protection_domain) { + return true; + } } return false; } @@ -283,6 +293,7 @@ DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash, } + InstanceKlass* Dictionary::find(unsigned int hash, Symbol* name, Handle protection_domain) { NoSafepointVerifier nsv; @@ -307,11 +318,11 @@ InstanceKlass* Dictionary::find_class(unsigned int hash, return (entry != NULL) ? entry->instance_klass() : NULL; } - void Dictionary::add_protection_domain(int index, unsigned int hash, InstanceKlass* klass, Handle protection_domain, TRAPS) { + assert(java_lang_System::allow_security_manager(), "only needed if security manager allowed"); Symbol* klass_name = klass->name(); DictionaryEntry* entry = get_entry(index, hash, klass_name); diff --git a/src/hotspot/share/classfile/dictionary.hpp b/src/hotspot/share/classfile/dictionary.hpp index ff6ba0e2960..478ae05e114 100644 --- a/src/hotspot/share/classfile/dictionary.hpp +++ b/src/hotspot/share/classfile/dictionary.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -153,14 +153,7 @@ class DictionaryEntry : public HashtableEntry { void set_pd_set(ProtectionDomainEntry* new_head) { _pd_set = new_head; } // Tells whether the initiating class' protection domain can access the klass in this entry - bool is_valid_protection_domain(Handle protection_domain) { - if (!ProtectionDomainVerification) return true; - - return protection_domain() == NULL - ? true - : contains_protection_domain(protection_domain()); - } - + inline bool is_valid_protection_domain(Handle protection_domain); void verify_protection_domain_set(); bool equals(const Symbol* class_name) const { diff --git a/src/hotspot/share/classfile/javaAssertions.hpp b/src/hotspot/share/classfile/javaAssertions.hpp index b2fa038b24a..58d03eacd48 100644 --- a/src/hotspot/share/classfile/javaAssertions.hpp +++ b/src/hotspot/share/classfile/javaAssertions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "oops/objArrayOop.hpp" #include "oops/typeArrayOop.hpp" +#include "runtime/handles.hpp" #include "utilities/exceptions.hpp" #include "utilities/ostream.hpp" diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index a0467dddcfe..614286beae1 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -41,6 +41,7 @@ #include "interpreter/linkResolver.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" +#include "memory/archiveBuilder.hpp" #include "memory/heapShared.inline.hpp" #include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" @@ -857,12 +858,14 @@ static void initialize_static_field(fieldDescriptor* fd, Handle mirror, TRAPS) { break; case T_OBJECT: { - assert(fd->signature() == vmSymbols::string_signature(), + // Can't use vmSymbols::string_signature() as fd->signature() may have been relocated + // during DumpSharedSpaces + assert(fd->signature()->equals("Ljava/lang/String;"), "just checking"); if (DumpSharedSpaces && HeapShared::is_archived_object(mirror())) { // Archive the String field and update the pointer. oop s = mirror()->obj_field(fd->offset()); - oop archived_s = StringTable::create_archived_string(s, CHECK); + oop archived_s = StringTable::create_archived_string(s); mirror()->obj_field_put(fd->offset(), archived_s); } else { oop string = fd->string_initial_value(CHECK); @@ -1130,7 +1133,22 @@ class ResetMirrorField: public FieldClosure { } }; -void java_lang_Class::archive_basic_type_mirrors(TRAPS) { +static void set_klass_field_in_archived_mirror(oop mirror_obj, int offset, Klass* k) { + assert(java_lang_Class::is_instance(mirror_obj), "must be"); + // this is the copy of k in the output buffer + Klass* copy = ArchiveBuilder::get_relocated_klass(k); + + // This is the address of k, if the archive is loaded at the requested location + Klass* def = ArchiveBuilder::current()->to_requested(copy); + + log_debug(cds, heap, mirror)( + "Relocate mirror metadata field at %d from " PTR_FORMAT " ==> " PTR_FORMAT, + offset, p2i(k), p2i(def)); + + mirror_obj->metadata_field_put(offset, def); +} + +void java_lang_Class::archive_basic_type_mirrors() { assert(HeapShared::is_heap_object_archiving_allowed(), "HeapShared::is_heap_object_archiving_allowed() must be true"); @@ -1139,18 +1157,17 @@ void java_lang_Class::archive_basic_type_mirrors(TRAPS) { oop m = Universe::_mirrors[t].resolve(); if (m != NULL) { // Update the field at _array_klass_offset to point to the relocated array klass. - oop archived_m = HeapShared::archive_heap_object(m, THREAD); + oop archived_m = HeapShared::archive_heap_object(m); assert(archived_m != NULL, "sanity"); Klass *ak = (Klass*)(archived_m->metadata_field(_array_klass_offset)); assert(ak != NULL || t == T_VOID, "should not be NULL"); if (ak != NULL) { - Klass *reloc_ak = MetaspaceShared::get_relocated_klass(ak, true); - archived_m->metadata_field_put(_array_klass_offset, reloc_ak); + set_klass_field_in_archived_mirror(archived_m, _array_klass_offset, ak); } // Clear the fields. Just to be safe Klass *k = m->klass(); - Handle archived_mirror_h(THREAD, archived_m); + Handle archived_mirror_h(Thread::current(), archived_m); ResetMirrorField reset(archived_mirror_h); InstanceKlass::cast(k)->do_nonstatic_fields(&reset); @@ -1170,7 +1187,7 @@ void java_lang_Class::archive_basic_type_mirrors(TRAPS) { // archived mirror is restored. If archived java heap data cannot // be used at runtime, new mirror object is created for the shared // class. The _has_archived_raw_mirror is cleared also during the process. -oop java_lang_Class::archive_mirror(Klass* k, TRAPS) { +oop java_lang_Class::archive_mirror(Klass* k) { assert(HeapShared::is_heap_object_archiving_allowed(), "HeapShared::is_heap_object_archiving_allowed() must be true"); @@ -1205,12 +1222,12 @@ oop java_lang_Class::archive_mirror(Klass* k, TRAPS) { } // Now start archiving the mirror object - oop archived_mirror = HeapShared::archive_heap_object(mirror, THREAD); + oop archived_mirror = HeapShared::archive_heap_object(mirror); if (archived_mirror == NULL) { return NULL; } - archived_mirror = process_archived_mirror(k, mirror, archived_mirror, THREAD); + archived_mirror = process_archived_mirror(k, mirror, archived_mirror); if (archived_mirror == NULL) { return NULL; } @@ -1227,12 +1244,11 @@ oop java_lang_Class::archive_mirror(Klass* k, TRAPS) { // The process is based on create_mirror(). oop java_lang_Class::process_archived_mirror(Klass* k, oop mirror, - oop archived_mirror, - Thread *THREAD) { + oop archived_mirror) { // Clear nonstatic fields in archived mirror. Some of the fields will be set // to archived metadata and objects below. Klass *c = archived_mirror->klass(); - Handle archived_mirror_h(THREAD, archived_mirror); + Handle archived_mirror_h(Thread::current(), archived_mirror); ResetMirrorField reset(archived_mirror_h); InstanceKlass::cast(c)->do_nonstatic_fields(&reset); @@ -1247,7 +1263,7 @@ oop java_lang_Class::process_archived_mirror(Klass* k, oop mirror, assert(k->is_objArray_klass(), "Must be"); Klass* element_klass = ObjArrayKlass::cast(k)->element_klass(); assert(element_klass != NULL, "Must have an element klass"); - archived_comp_mirror = archive_mirror(element_klass, THREAD); + archived_comp_mirror = archive_mirror(element_klass); if (archived_comp_mirror == NULL) { return NULL; } @@ -1273,21 +1289,13 @@ oop java_lang_Class::process_archived_mirror(Klass* k, oop mirror, // The archived mirror's field at _klass_offset is still pointing to the original // klass. Updated the field in the archived mirror to point to the relocated // klass in the archive. - Klass *reloc_k = MetaspaceShared::get_relocated_klass(as_Klass(mirror), true); - log_debug(cds, heap, mirror)( - "Relocate mirror metadata field at _klass_offset from " PTR_FORMAT " ==> " PTR_FORMAT, - p2i(as_Klass(mirror)), p2i(reloc_k)); - archived_mirror->metadata_field_put(_klass_offset, reloc_k); + set_klass_field_in_archived_mirror(archived_mirror, _klass_offset, as_Klass(mirror)); // The field at _array_klass_offset is pointing to the original one dimension // higher array klass if exists. Relocate the pointer. Klass *arr = array_klass_acquire(mirror); if (arr != NULL) { - Klass *reloc_arr = MetaspaceShared::get_relocated_klass(arr, true); - log_debug(cds, heap, mirror)( - "Relocate mirror metadata field at _array_klass_offset from " PTR_FORMAT " ==> " PTR_FORMAT, - p2i(arr), p2i(reloc_arr)); - archived_mirror->metadata_field_put(_array_klass_offset, reloc_arr); + set_klass_field_in_archived_mirror(archived_mirror, _array_klass_offset, arr); } return archived_mirror; } @@ -4404,18 +4412,41 @@ int java_lang_System::_static_in_offset; int java_lang_System::_static_out_offset; int java_lang_System::_static_err_offset; int java_lang_System::_static_security_offset; +int java_lang_System::_static_allow_security_offset; +int java_lang_System::_static_never_offset; #define SYSTEM_FIELDS_DO(macro) \ macro(_static_in_offset, k, "in", input_stream_signature, true); \ macro(_static_out_offset, k, "out", print_stream_signature, true); \ macro(_static_err_offset, k, "err", print_stream_signature, true); \ - macro(_static_security_offset, k, "security", security_manager_signature, true) + macro(_static_security_offset, k, "security", security_manager_signature, true); \ + macro(_static_allow_security_offset, k, "allowSecurityManager", int_signature, true); \ + macro(_static_never_offset, k, "NEVER", int_signature, true) void java_lang_System::compute_offsets() { InstanceKlass* k = vmClasses::System_klass(); SYSTEM_FIELDS_DO(FIELD_COMPUTE_OFFSET); } +// This field tells us that a security manager can never be installed so we +// can completely skip populating the ProtectionDomainCacheTable. +bool java_lang_System::allow_security_manager() { + static int initialized = false; + static bool allowed = true; // default + if (!initialized) { + oop base = vmClasses::System_klass()->static_field_base_raw(); + int never = base->int_field(_static_never_offset); + allowed = (base->int_field(_static_allow_security_offset) != never); + } + return allowed; +} + +// This field tells us that a security manager is installed. +bool java_lang_System::has_security_manager() { + oop base = vmClasses::System_klass()->static_field_base_raw(); + return base->obj_field(_static_security_offset) != NULL; +} + #if INCLUDE_CDS void java_lang_System::serialize_offsets(SerializeClosure* f) { SYSTEM_FIELDS_DO(FIELD_SERIALIZE_OFFSET); diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp index 93f034de444..85dd7a4de51 100644 --- a/src/hotspot/share/classfile/javaClasses.hpp +++ b/src/hotspot/share/classfile/javaClasses.hpp @@ -277,9 +277,9 @@ class java_lang_Class : AllStatic { // Archiving static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; - static void archive_basic_type_mirrors(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; - static oop archive_mirror(Klass* k, TRAPS) NOT_CDS_JAVA_HEAP_RETURN_(NULL); - static oop process_archived_mirror(Klass* k, oop mirror, oop archived_mirror, Thread *THREAD) + static void archive_basic_type_mirrors() NOT_CDS_JAVA_HEAP_RETURN; + static oop archive_mirror(Klass* k) NOT_CDS_JAVA_HEAP_RETURN_(NULL); + static oop process_archived_mirror(Klass* k, oop mirror, oop archived_mirror) NOT_CDS_JAVA_HEAP_RETURN_(NULL); static bool restore_archived_mirror(Klass *k, Handle class_loader, Handle module, Handle protection_domain, @@ -1372,11 +1372,15 @@ class java_lang_System : AllStatic { static int _static_out_offset; static int _static_err_offset; static int _static_security_offset; + static int _static_allow_security_offset; + static int _static_never_offset; public: static int in_offset() { CHECK_INIT(_static_in_offset); } static int out_offset() { CHECK_INIT(_static_out_offset); } static int err_offset() { CHECK_INIT(_static_err_offset); } + static bool allow_security_manager(); + static bool has_security_manager(); static void compute_offsets(); static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; diff --git a/src/hotspot/share/classfile/klassFactory.cpp b/src/hotspot/share/classfile/klassFactory.cpp index a02d01020b5..e3f41ee0b45 100644 --- a/src/hotspot/share/classfile/klassFactory.cpp +++ b/src/hotspot/share/classfile/klassFactory.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ #include "classfile/classLoadInfo.hpp" #include "classfile/klassFactory.hpp" #include "memory/filemap.hpp" -#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "prims/jvmtiEnvBase.hpp" #include "prims/jvmtiRedefineClasses.hpp" @@ -98,7 +97,7 @@ InstanceKlass* KlassFactory::check_shared_class_file_load_hook( } if (class_loader.is_null()) { - new_ik->set_classpath_index(path_index, THREAD); + new_ik->set_classpath_index(path_index); } return new_ik; diff --git a/src/hotspot/share/classfile/loaderConstraints.cpp b/src/hotspot/share/classfile/loaderConstraints.cpp index d0bf7052821..3caaddb3cb2 100644 --- a/src/hotspot/share/classfile/loaderConstraints.cpp +++ b/src/hotspot/share/classfile/loaderConstraints.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "classfile/loaderConstraints.hpp" #include "logging/log.hpp" #include "memory/resourceArea.hpp" +#include "oops/klass.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/safepoint.hpp" diff --git a/src/hotspot/share/classfile/moduleEntry.cpp b/src/hotspot/share/classfile/moduleEntry.cpp index 08c97c9e7a7..7d9c9001b40 100644 --- a/src/hotspot/share/classfile/moduleEntry.cpp +++ b/src/hotspot/share/classfile/moduleEntry.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,6 @@ #include "memory/archiveUtils.hpp" #include "memory/filemap.hpp" #include "memory/heapShared.hpp" -#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/oopHandle.inline.hpp" @@ -368,6 +367,11 @@ ModuleEntryTable::~ModuleEntryTable() { assert(new_entry_free_list() == NULL, "entry present on ModuleEntryTable's free list"); } +void ModuleEntry::set_loader_data(ClassLoaderData* cld) { + assert(!cld->has_class_mirror_holder(), "Unexpected has_class_mirror_holder cld"); + _loader_data = cld; +} + #if INCLUDE_CDS_JAVA_HEAP typedef ResourceHashtable< const ModuleEntry*, @@ -380,7 +384,7 @@ static ArchivedModuleEntries* _archive_modules_entries = NULL; ModuleEntry* ModuleEntry::allocate_archived_entry() const { assert(is_named(), "unnamed packages/modules are not archived"); - ModuleEntry* archived_entry = (ModuleEntry*)MetaspaceShared::read_write_space_alloc(sizeof(ModuleEntry)); + ModuleEntry* archived_entry = (ModuleEntry*)ArchiveBuilder::rw_region_alloc(sizeof(ModuleEntry)); memcpy((void*)archived_entry, (void*)this, sizeof(ModuleEntry)); if (_archive_modules_entries == NULL) { @@ -405,7 +409,7 @@ Array* ModuleEntry::write_growable_array(GrowableArray* archived_array = NULL; int length = (array == NULL) ? 0 : array->length(); if (length > 0) { - archived_array = MetaspaceShared::new_ro_array(length); + archived_array = ArchiveBuilder::new_ro_array(length); for (int i = 0; i < length; i++) { ModuleEntry* archived_entry = get_archived_entry(array->at(i)); archived_array->at_put(i, archived_entry); @@ -513,7 +517,7 @@ void ModuleEntryTable::iterate_symbols(MetaspaceClosure* closure) { } Array* ModuleEntryTable::allocate_archived_entries() { - Array* archived_modules = MetaspaceShared::new_rw_array(number_of_entries()); + Array* archived_modules = ArchiveBuilder::new_rw_array(number_of_entries()); int n = 0; for (int i = 0; i < table_size(); ++i) { for (ModuleEntry* m = bucket(i); m != NULL; m = m->next()) { diff --git a/src/hotspot/share/classfile/moduleEntry.hpp b/src/hotspot/share/classfile/moduleEntry.hpp index e2bae48948f..959fcac74e3 100644 --- a/src/hotspot/share/classfile/moduleEntry.hpp +++ b/src/hotspot/share/classfile/moduleEntry.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,10 +26,8 @@ #define SHARE_CLASSFILE_MODULEENTRY_HPP #include "jni.h" -#include "classfile/classLoaderData.hpp" #include "oops/oopHandle.hpp" #include "oops/symbol.hpp" -#include "runtime/jniHandles.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.hpp" @@ -47,6 +45,7 @@ #define JAVA_BASE_NAME_LEN 9 template class Array; +class ClassLoaderData; class MetaspaceClosure; class ModuleClosure; @@ -113,11 +112,7 @@ class ModuleEntry : public HashtableEntry { void set_shared_protection_domain(ClassLoaderData *loader_data, Handle pd); ClassLoaderData* loader_data() const { return _loader_data; } - - void set_loader_data(ClassLoaderData* cld) { - assert(!cld->has_class_mirror_holder(), "Unexpected has_class_mirror_holder cld"); - _loader_data = cld; - } + void set_loader_data(ClassLoaderData* cld); Symbol* version() const { return _version; } void set_version(Symbol* version); diff --git a/src/hotspot/share/classfile/modules.cpp b/src/hotspot/share/classfile/modules.cpp index e4de916b471..e8b107e34de 100644 --- a/src/hotspot/share/classfile/modules.cpp +++ b/src/hotspot/share/classfile/modules.cpp @@ -48,6 +48,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/jniHandles.inline.hpp" +#include "utilities/formatBuffer.hpp" #include "utilities/stringUtils.hpp" #include "utilities/utf8.hpp" diff --git a/src/hotspot/share/classfile/packageEntry.cpp b/src/hotspot/share/classfile/packageEntry.cpp index 8e5c826dbad..b32a6a51102 100644 --- a/src/hotspot/share/classfile/packageEntry.cpp +++ b/src/hotspot/share/classfile/packageEntry.cpp @@ -23,13 +23,13 @@ */ #include "precompiled.hpp" +#include "classfile/classLoaderData.hpp" #include "classfile/moduleEntry.hpp" #include "classfile/packageEntry.hpp" #include "classfile/vmSymbols.hpp" #include "logging/log.hpp" #include "memory/archiveBuilder.hpp" #include "memory/archiveUtils.hpp" -#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "oops/array.hpp" #include "oops/symbol.hpp" @@ -208,7 +208,7 @@ static ArchivedPackageEntries* _archived_packages_entries = NULL; PackageEntry* PackageEntry::allocate_archived_entry() const { assert(!in_unnamed_module(), "unnamed packages/modules are not archived"); - PackageEntry* archived_entry = (PackageEntry*)MetaspaceShared::read_write_space_alloc(sizeof(PackageEntry)); + PackageEntry* archived_entry = (PackageEntry*)ArchiveBuilder::rw_region_alloc(sizeof(PackageEntry)); memcpy((void*)archived_entry, (void*)this, sizeof(PackageEntry)); if (_archived_packages_entries == NULL) { @@ -278,7 +278,7 @@ Array* PackageEntryTable::allocate_archived_entries() { } } - Array* archived_packages = MetaspaceShared::new_rw_array(n); + Array* archived_packages = ArchiveBuilder::new_rw_array(n); for (n = 0, i = 0; i < table_size(); ++i) { for (PackageEntry* p = bucket(i); p != NULL; p = p->next()) { if (p->module()->name() != NULL) { diff --git a/src/hotspot/share/classfile/placeholders.cpp b/src/hotspot/share/classfile/placeholders.cpp index 9f96963cc83..aa2e30acf07 100644 --- a/src/hotspot/share/classfile/placeholders.cpp +++ b/src/hotspot/share/classfile/placeholders.cpp @@ -112,7 +112,7 @@ void PlaceholderEntry::set_threadQ(SeenThread* seenthread, PlaceholderTable::cla // Doubly-linked list of Threads per action for class/classloader pair // Class circularity support: links in thread before loading superclass -// bootstrapsearchpath support: links in a thread before load_instance_class +// bootstrap loader support: links in a thread before load_instance_class // definers: use as queue of define requestors, including owner of // define token. Appends for debugging of requestor order void PlaceholderEntry::add_seen_thread(Thread* thread, PlaceholderTable::classloadAction action) { @@ -120,6 +120,9 @@ void PlaceholderEntry::add_seen_thread(Thread* thread, PlaceholderTable::classlo SeenThread* threadEntry = new SeenThread(thread); SeenThread* seen = actionToQueue(action); + assert(action != PlaceholderTable::LOAD_INSTANCE || seen == NULL, + "Only one LOAD_INSTANCE allowed at a time"); + if (seen == NULL) { set_threadQ(threadEntry, action); return; diff --git a/src/hotspot/share/classfile/placeholders.hpp b/src/hotspot/share/classfile/placeholders.hpp index 4e364dcfab0..fdf0a51857a 100644 --- a/src/hotspot/share/classfile/placeholders.hpp +++ b/src/hotspot/share/classfile/placeholders.hpp @@ -122,8 +122,8 @@ class PlaceholderEntry : public HashtableEntry { InstanceKlass* _instanceKlass; // InstanceKlass from successful define SeenThread* _superThreadQ; // doubly-linked queue of Threads loading a superclass for this class SeenThread* _loadInstanceThreadQ; // loadInstance thread - // can be multiple threads if classloader object lock broken by application - // or if classloader supports parallel classloading + // This can't be multiple threads since class loading waits for + // this token to be removed. SeenThread* _defineThreadQ; // queue of Threads trying to define this class // including _definer diff --git a/src/hotspot/share/classfile/protectionDomainCache.cpp b/src/hotspot/share/classfile/protectionDomainCache.cpp index b02ec1a8602..367abceb17a 100644 --- a/src/hotspot/share/classfile/protectionDomainCache.cpp +++ b/src/hotspot/share/classfile/protectionDomainCache.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "classfile/classLoaderDataGraph.hpp" #include "classfile/dictionary.hpp" +#include "classfile/javaClasses.hpp" #include "classfile/protectionDomainCache.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" @@ -66,6 +67,9 @@ class CleanProtectionDomainEntries : public CLDClosure { }; void ProtectionDomainCacheTable::unlink() { + // The dictionary entries _pd_set field should be null also, so nothing to do. + assert(java_lang_System::allow_security_manager(), "should not be called otherwise"); + { // First clean cached pd lists in loaded CLDs // It's unlikely, but some loaded classes in a dictionary might diff --git a/src/hotspot/share/classfile/resolutionErrors.cpp b/src/hotspot/share/classfile/resolutionErrors.cpp index d248a5e55ec..47eca140606 100644 --- a/src/hotspot/share/classfile/resolutionErrors.cpp +++ b/src/hotspot/share/classfile/resolutionErrors.cpp @@ -27,6 +27,7 @@ #include "memory/allocation.hpp" #include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" +#include "oops/klass.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/safepoint.hpp" diff --git a/src/hotspot/share/classfile/stringTable.cpp b/src/hotspot/share/classfile/stringTable.cpp index 52b357563e6..8fe73d6759c 100644 --- a/src/hotspot/share/classfile/stringTable.cpp +++ b/src/hotspot/share/classfile/stringTable.cpp @@ -34,7 +34,7 @@ #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" -#include "memory/filemap.hpp" +#include "memory/archiveBuilder.hpp" #include "memory/heapShared.inline.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" @@ -717,17 +717,18 @@ oop StringTable::lookup_shared(const jchar* name, int len, unsigned int hash) { return _shared_table.lookup(name, hash, len); } -oop StringTable::create_archived_string(oop s, Thread* THREAD) { +oop StringTable::create_archived_string(oop s) { assert(DumpSharedSpaces, "this function is only used with -Xshare:dump"); + assert(java_lang_String::is_instance(s), "sanity"); assert(!HeapShared::is_archived_object(s), "sanity"); oop new_s = NULL; typeArrayOop v = java_lang_String::value_no_keepalive(s); - typeArrayOop new_v = (typeArrayOop)HeapShared::archive_heap_object(v, THREAD); + typeArrayOop new_v = (typeArrayOop)HeapShared::archive_heap_object(v); if (new_v == NULL) { return NULL; } - new_s = HeapShared::archive_heap_object(s, THREAD); + new_s = HeapShared::archive_heap_object(s); if (new_s == NULL) { return NULL; } @@ -744,7 +745,7 @@ class CopyToArchive : StackObj { bool do_entry(oop s, bool value_ignored) { assert(s != NULL, "sanity"); unsigned int hash = java_lang_String::hash_code(s); - oop new_s = StringTable::create_archived_string(s, Thread::current()); + oop new_s = StringTable::create_archived_string(s); if (new_s == NULL) { return true; } @@ -759,7 +760,7 @@ void StringTable::write_to_archive(const DumpedInternedStrings* dumped_interned_ assert(HeapShared::is_heap_object_archiving_allowed(), "must be"); _shared_table.reset(); - CompactHashtableWriter writer(_items_count, &MetaspaceShared::stats()->string); + CompactHashtableWriter writer(_items_count, ArchiveBuilder::string_stats()); // Copy the interned strings into the "string space" within the java heap CopyToArchive copier(&writer); diff --git a/src/hotspot/share/classfile/stringTable.hpp b/src/hotspot/share/classfile/stringTable.hpp index 41a8f502584..2b4797b2b87 100644 --- a/src/hotspot/share/classfile/stringTable.hpp +++ b/src/hotspot/share/classfile/stringTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,7 +107,7 @@ class StringTable : public CHeapObj{ private: static oop lookup_shared(const jchar* name, int len, unsigned int hash) NOT_CDS_JAVA_HEAP_RETURN_(NULL); public: - static oop create_archived_string(oop s, Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN_(NULL); + static oop create_archived_string(oop s) NOT_CDS_JAVA_HEAP_RETURN_(NULL); static void shared_oops_do(OopClosure* f) NOT_CDS_JAVA_HEAP_RETURN; static void write_to_archive(const DumpedInternedStrings* dumped_interned_strings) NOT_CDS_JAVA_HEAP_RETURN; static void serialize_shared_table_header(SerializeClosure* soc) NOT_CDS_JAVA_HEAP_RETURN; diff --git a/src/hotspot/share/classfile/symbolTable.cpp b/src/hotspot/share/classfile/symbolTable.cpp index 9c914d6cd5a..26f3c6ad379 100644 --- a/src/hotspot/share/classfile/symbolTable.cpp +++ b/src/hotspot/share/classfile/symbolTable.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/altHashing.hpp" +#include "classfile/classLoaderData.hpp" #include "classfile/compactHashtable.hpp" #include "classfile/javaClasses.hpp" #include "classfile/symbolTable.hpp" @@ -31,7 +32,6 @@ #include "memory/archiveBuilder.hpp" #include "memory/dynamicArchive.hpp" #include "memory/metaspaceClosure.hpp" -#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" @@ -584,6 +584,7 @@ void SymbolTable::dump(outputStream* st, bool verbose) { #if INCLUDE_CDS void SymbolTable::copy_shared_symbol_table(GrowableArray* symbols, CompactHashtableWriter* writer) { + ArchiveBuilder* builder = ArchiveBuilder::current(); int len = symbols->length(); for (int i = 0; i < len; i++) { Symbol* sym = ArchiveBuilder::get_relocated_symbol(symbols->at(i)); @@ -591,10 +592,7 @@ void SymbolTable::copy_shared_symbol_table(GrowableArray* symbols, assert(fixed_hash == hash_symbol((const char*)sym->bytes(), sym->utf8_length(), false), "must not rehash during dumping"); sym->set_permanent(); - if (DynamicDumpSharedSpaces) { - sym = DynamicArchive::buffer_to_target(sym); - } - writer->add(fixed_hash, MetaspaceShared::object_delta_u4(sym)); + writer->add(fixed_hash, builder->buffer_to_offset_u4((address)sym)); } } @@ -603,21 +601,11 @@ size_t SymbolTable::estimate_size_for_archive() { } void SymbolTable::write_to_archive(GrowableArray* symbols) { - CompactHashtableWriter writer(int(_items_count), - &MetaspaceShared::stats()->symbol); + CompactHashtableWriter writer(int(_items_count), ArchiveBuilder::symbol_stats()); copy_shared_symbol_table(symbols, &writer); if (!DynamicDumpSharedSpaces) { _shared_table.reset(); writer.dump(&_shared_table, "symbol"); - - // Verify the written shared table is correct -- at this point, - // vmSymbols has already been relocated to point to the archived - // version of the Symbols. - Symbol* sym = vmSymbols::java_lang_Object(); - const char* name = (const char*)sym->bytes(); - int len = sym->utf8_length(); - unsigned int hash = hash_symbol(name, len, _alt_hash); - assert(sym == _shared_table.lookup(name, hash, len), "sanity"); } else { _dynamic_shared_table.reset(); writer.dump(&_dynamic_shared_table, "symbol"); diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index 49bf6aeff6f..6533f77772a 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -154,14 +154,14 @@ ClassLoaderData* SystemDictionary::register_loader(Handle class_loader, bool cre // ---------------------------------------------------------------------------- // Parallel class loading check -bool SystemDictionary::is_parallelCapable(Handle class_loader) { +bool is_parallelCapable(Handle class_loader) { if (class_loader.is_null()) return true; if (AlwaysLockClassLoader) return false; return java_lang_ClassLoader::parallelCapable(class_loader()); } // ---------------------------------------------------------------------------- // ParallelDefineClass flag does not apply to bootclass loader -bool SystemDictionary::is_parallelDefine(Handle class_loader) { +bool is_parallelDefine(Handle class_loader) { if (class_loader.is_null()) return false; if (AllowParallelDefineClass && java_lang_ClassLoader::parallelCapable(class_loader())) { return true; @@ -188,7 +188,7 @@ bool SystemDictionary::is_platform_class_loader(oop class_loader) { return (class_loader->klass() == vmClasses::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass()); } -Handle SystemDictionary::compute_loader_lock_object(Thread* thread, Handle class_loader) { +Handle SystemDictionary::get_loader_lock_or_null(Handle class_loader) { // If class_loader is NULL or parallelCapable, the JVM doesn't acquire a lock while loading. if (is_parallelCapable(class_loader)) { return Handle(); @@ -510,54 +510,54 @@ void SystemDictionary::validate_protection_domain(InstanceKlass* klass, Handle protection_domain, TRAPS) { // Now we have to call back to java to check if the initating class has access - JavaValue result(T_VOID); - LogTarget(Debug, protectiondomain) lt; - if (lt.is_enabled()) { - ResourceMark rm(THREAD); - // Print out trace information - LogStream ls(lt); - ls.print_cr("Checking package access"); - if (class_loader() != NULL) { + assert(class_loader() != NULL, "Should not call this"); + assert(protection_domain() != NULL, "Should not call this"); + + // We only have to call checkPackageAccess if there's a security manager installed. + if (java_lang_System::has_security_manager()) { + + // This handle and the class_loader handle passed in keeps this class from + // being unloaded through several GC points. + // The class_loader handle passed in is the initiating loader. + Handle mirror(THREAD, klass->java_mirror()); + + InstanceKlass* system_loader = vmClasses::ClassLoader_klass(); + JavaValue result(T_VOID); + JavaCalls::call_special(&result, + class_loader, + system_loader, + vmSymbols::checkPackageAccess_name(), + vmSymbols::class_protectiondomain_signature(), + mirror, + protection_domain, + THREAD); + + LogTarget(Debug, protectiondomain) lt; + if (lt.is_enabled()) { + ResourceMark rm(THREAD); + // Print out trace information + LogStream ls(lt); + ls.print_cr("Checking package access"); ls.print("class loader: "); class_loader()->print_value_on(&ls); - } else { - ls.print_cr("class loader: NULL"); - } - if (protection_domain() != NULL) { ls.print(" protection domain: "); protection_domain()->print_value_on(&ls); - } else { - ls.print_cr(" protection domain: NULL"); + ls.print(" loading: "); klass->print_value_on(&ls); + if (HAS_PENDING_EXCEPTION) { + ls.print_cr(" DENIED !!!!!!!!!!!!!!!!!!!!!"); + } else { + ls.print_cr(" granted"); + } } - ls.print(" loading: "); klass->print_value_on(&ls); - ls.cr(); - } - - // This handle and the class_loader handle passed in keeps this class from - // being unloaded through several GC points. - // The class_loader handle passed in is the initiating loader. - Handle mirror(THREAD, klass->java_mirror()); - - InstanceKlass* system_loader = vmClasses::ClassLoader_klass(); - JavaCalls::call_special(&result, - class_loader, - system_loader, - vmSymbols::checkPackageAccess_name(), - vmSymbols::class_protectiondomain_signature(), - mirror, - protection_domain, - THREAD); - if (HAS_PENDING_EXCEPTION) { - log_debug(protectiondomain)("DENIED !!!!!!!!!!!!!!!!!!!!!"); - } else { - log_debug(protectiondomain)("granted"); + if (HAS_PENDING_EXCEPTION) return; } - if (HAS_PENDING_EXCEPTION) return; - // If no exception has been thrown, we have validated the protection domain // Insert the protection domain of the initiating class into the set. + // We still have to add the protection_domain to the dictionary in case a new + // security manager is installed later. Calls to load the same class with class loader + // and protection domain are expected to succeed. { ClassLoaderData* loader_data = class_loader_data(class_loader); Dictionary* dictionary = loader_data->dictionary(); @@ -620,12 +620,9 @@ void SystemDictionary::double_lock_wait(Thread* thread, Handle lockObject) { // super class loading here. // This also is critical in cases where the original thread gets stalled // even in non-circularity situations. -// Note: must call resolve_super_or_fail even if null super - -// to force placeholder entry creation for this class for circularity detection -// Caller must check for pending exception // Returns non-null Klass* if other thread has completed load -// and we are done, -// If return null Klass* and no pending exception, the caller must load the class +// and we are done. If this returns a null Klass* and no pending exception, +// the caller must load the class. InstanceKlass* SystemDictionary::handle_parallel_super_load( Symbol* name, Symbol* superclassname, Handle class_loader, Handle protection_domain, Handle lockObject, TRAPS) { @@ -634,14 +631,7 @@ InstanceKlass* SystemDictionary::handle_parallel_super_load( Dictionary* dictionary = loader_data->dictionary(); unsigned int name_hash = dictionary->compute_hash(name); - // superk is not used, resolve_super called for circularity check only - // This code is reached in two situations. One if this thread - // is loading the same class twice (e.g. ClassCircularity, or - // java.lang.instrument). - // The second is if another thread started the resolve_super first - // and has not yet finished. - // In both cases the original caller will clean up the placeholder - // entry on error. + // superk is not used; resolve_super_or_fail is called for circularity check only. Klass* superk = SystemDictionary::resolve_super_or_fail(name, superclassname, class_loader, @@ -653,7 +643,6 @@ InstanceKlass* SystemDictionary::handle_parallel_super_load( // Serial class loaders and bootstrap classloader do wait for superclass loads if (!class_loader.is_null() && is_parallelCapable(class_loader)) { MutexLocker mu(THREAD, SystemDictionary_lock); - // Check if classloading completed while we were loading superclass or waiting return dictionary->find_class(name_hash, name); } @@ -753,7 +742,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, // the define. // ParallelCapable Classloaders and the bootstrap classloader // do not acquire lock here. - Handle lockObject = compute_loader_lock_object(THREAD, class_loader); + Handle lockObject = get_loader_lock_or_null(class_loader); ObjectLocker ol(lockObject, THREAD); // Check again (after locking) if the class already exists in SystemDictionary @@ -809,10 +798,8 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, // but only allows a single thread to load a class/classloader pair. // The LOAD_INSTANCE placeholder is the mechanism for mutual exclusion. // case 2. parallelCapable user level classloaders - // These class loaders don't lock the object until load_instance_class is - // called after this placeholder is added. - // Allow parallel classloading of a class/classloader pair where mutual - // exclusion is provided by this lock in the class loader Java code. + // These class loaders lock a per-class object lock when ClassLoader.loadClass() + // is called. A LOAD_INSTANCE placeholder isn't used for mutual exclusion. // case 3. traditional classloaders that rely on the classloader object lock // There should be no need for need for LOAD_INSTANCE, except: // case 4. traditional class loaders that break the classloader object lock @@ -821,65 +808,64 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, // and that lock is still held when calling classloader's loadClass. // For these classloaders, we ensure that the first requestor // completes the load and other requestors wait for completion. - { + if (class_loader.is_null() || !is_parallelCapable(class_loader)) { MutexLocker mu(THREAD, SystemDictionary_lock); - if (class_loader.is_null() || !is_parallelCapable(class_loader)) { - PlaceholderEntry* oldprobe = placeholders()->get_entry(name_hash, name, loader_data); - if (oldprobe != NULL) { - // only need check_seen_thread once, not on each loop - // 6341374 java/lang/Instrument with -Xcomp - if (oldprobe->check_seen_thread(THREAD, PlaceholderTable::LOAD_INSTANCE)) { - throw_circularity_error = true; - } else { - // case 3: traditional: should never see load_in_progress. - while (!class_has_been_loaded && oldprobe != NULL && oldprobe->instance_load_in_progress()) { - - // case 1: bootstrap classloader: prevent futile classloading, - // wait on first requestor - if (class_loader.is_null()) { - SystemDictionary_lock->wait(); - } else { + PlaceholderEntry* oldprobe = placeholders()->get_entry(name_hash, name, loader_data); + if (oldprobe != NULL) { + // only need check_seen_thread once, not on each loop + // 6341374 java/lang/Instrument with -Xcomp + if (oldprobe->check_seen_thread(THREAD, PlaceholderTable::LOAD_INSTANCE)) { + throw_circularity_error = true; + } else { + // case 3: traditional: should never see load_in_progress. + while (!class_has_been_loaded && oldprobe != NULL && oldprobe->instance_load_in_progress()) { + + // case 1: bootstrap classloader: prevent futile classloading, + // wait on first requestor + if (class_loader.is_null()) { + SystemDictionary_lock->wait(); + } else { // case 4: traditional with broken classloader lock. wait on first // requestor. - double_lock_wait(THREAD, lockObject); - } - // Check if classloading completed while we were waiting - InstanceKlass* check = dictionary->find_class(name_hash, name); - if (check != NULL) { - // Klass is already loaded, so just return it - loaded_class = check; - class_has_been_loaded = true; - } - // check if other thread failed to load and cleaned up - oldprobe = placeholders()->get_entry(name_hash, name, loader_data); + double_lock_wait(THREAD, lockObject); } + // Check if classloading completed while we were waiting + InstanceKlass* check = dictionary->find_class(name_hash, name); + if (check != NULL) { + // Klass is already loaded, so just return it + loaded_class = check; + class_has_been_loaded = true; + } + // check if other thread failed to load and cleaned up + oldprobe = placeholders()->get_entry(name_hash, name, loader_data); } } } - // All cases: add LOAD_INSTANCE while holding the SystemDictionary_lock + // Add LOAD_INSTANCE while holding the SystemDictionary_lock if (!throw_circularity_error && !class_has_been_loaded) { - PlaceholderEntry* newprobe = placeholders()->find_and_add(name_hash, name, loader_data, - PlaceholderTable::LOAD_INSTANCE, NULL, THREAD); - load_instance_added = true; - // For class loaders that do not acquire the classloader object lock, - // if they did not catch another thread holding LOAD_INSTANCE, - // need a check analogous to the acquire ObjectLocker/find_class - // i.e. now that we hold the LOAD_INSTANCE token on loading this class/CL - // one final check if the load has already completed - // class loaders holding the ObjectLock shouldn't find the class here + // For the bootclass loader, if the thread did not catch another thread holding + // the LOAD_INSTANCE token, we need to check whether it completed loading + // while holding the SD_lock. InstanceKlass* check = dictionary->find_class(name_hash, name); if (check != NULL) { // Klass is already loaded, so return it after checking/adding protection domain loaded_class = check; class_has_been_loaded = true; + } else { + // Now we've got the LOAD_INSTANCE token. Threads will wait on loading to complete for this thread. + PlaceholderEntry* newprobe = placeholders()->find_and_add(name_hash, name, loader_data, + PlaceholderTable::LOAD_INSTANCE, + NULL, + THREAD); + load_instance_added = true; } } } // must throw error outside of owning lock if (throw_circularity_error) { - assert(!HAS_PENDING_EXCEPTION && load_instance_added == false,"circularity error cleanup"); + assert(!HAS_PENDING_EXCEPTION && !load_instance_added, "circularity error cleanup"); ResourceMark rm(THREAD); THROW_MSG_NULL(vmSymbols::java_lang_ClassCircularityError(), name->as_C_string()); } @@ -939,18 +925,15 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name, // Make sure we have the right class in the dictionary DEBUG_ONLY(verify_dictionary_entry(name, loaded_class)); - // return if the protection domain in NULL - if (protection_domain() == NULL) return loaded_class; - - // Check the protection domain has the right access - if (dictionary->is_valid_protection_domain(name_hash, name, + // Check if the protection domain is present it has the right access + if (protection_domain() != NULL && + java_lang_System::allow_security_manager() && + !dictionary->is_valid_protection_domain(name_hash, name, protection_domain)) { - return loaded_class; + // Verify protection domain. If it fails an exception is thrown + validate_protection_domain(loaded_class, class_loader, protection_domain, CHECK_NULL); } - // Verify protection domain. If it fails an exception is thrown - validate_protection_domain(loaded_class, class_loader, protection_domain, CHECK_NULL); - return loaded_class; } @@ -989,7 +972,6 @@ Klass* SystemDictionary::find(Symbol* class_name, protection_domain); } - // Look for a loaded instance or array klass by name. Do not do any loading. // return NULL in case of error. Klass* SystemDictionary::find_instance_or_array_klass(Symbol* class_name, @@ -1119,7 +1101,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name, // Classloaders that support parallelism, e.g. bootstrap classloader, // do not acquire lock here - Handle lockObject = compute_loader_lock_object(THREAD, class_loader); + Handle lockObject = get_loader_lock_or_null(class_loader); ObjectLocker ol(lockObject, THREAD); // Parse the stream and create a klass. @@ -1280,6 +1262,19 @@ bool SystemDictionary::check_shared_class_super_type(InstanceKlass* klass, Insta bool is_superclass, TRAPS) { assert(super_type->is_shared(), "must be"); + // Quick check if the super type has been already loaded. + // + Don't do it for unregistered classes -- they can be unloaded so + // super_type->class_loader_data() could be stale. + // + Don't check if loader data is NULL, ie. the super_type isn't fully loaded. + if (!super_type->is_shared_unregistered_class() && super_type->class_loader_data() != NULL) { + // Check if the super class is loaded by the current class_loader + Symbol* name = super_type->name(); + Klass* check = find(name, class_loader, protection_domain, CHECK_0); + if (check == super_type) { + return true; + } + } + Klass *found = resolve_super_or_fail(klass->name(), super_type->name(), class_loader, protection_domain, is_superclass, CHECK_0); if (found == super_type) { @@ -1415,7 +1410,7 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik, ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader()); { HandleMark hm(THREAD); - Handle lockObject = compute_loader_lock_object(THREAD, class_loader); + Handle lockObject = get_loader_lock_or_null(class_loader); ObjectLocker ol(lockObject, THREAD); // prohibited package check assumes all classes loaded from archive call // restore_unshareable_info which calls ik->set_package() @@ -1440,7 +1435,7 @@ void SystemDictionary::load_shared_class_misc(InstanceKlass* ik, ClassLoaderData // package was loaded. if (loader_data->is_the_null_class_loader_data()) { int path_index = ik->shared_classpath_index(); - ik->set_classpath_index(path_index, THREAD); + ik->set_classpath_index(path_index); } // notify a class loaded from shared object @@ -1624,7 +1619,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, Handle class_load // hole with systemDictionary updates and check_constraints if (!is_parallelCapable(class_loader)) { assert(ObjectSynchronizer::current_thread_holds_lock(THREAD->as_Java_thread(), - compute_loader_lock_object(THREAD, class_loader)), + get_loader_lock_or_null(class_loader)), "define called without lock"); } @@ -1836,12 +1831,16 @@ bool SystemDictionary::do_unloading(GCTimer* gc_timer) { if (unloading_occurred) { SymbolTable::trigger_cleanup(); - // Oops referenced by the protection domain cache table may get unreachable independently - // of the class loader (eg. cached protection domain oops). So we need to - // explicitly unlink them here. - // All protection domain oops are linked to the caller class, so if nothing - // unloads, this is not needed. - _pd_cache_table->trigger_cleanup(); + if (java_lang_System::allow_security_manager()) { + // Oops referenced by the protection domain cache table may get unreachable independently + // of the class loader (eg. cached protection domain oops). So we need to + // explicitly unlink them here. + // All protection domain oops are linked to the caller class, so if nothing + // unloads, this is not needed. + _pd_cache_table->trigger_cleanup(); + } else { + assert(_pd_cache_table->number_of_entries() == 0, "should be empty"); + } } return unloading_occurred; @@ -1870,21 +1869,10 @@ void SystemDictionary::initialize(TRAPS) { vmClasses::resolve_all(CHECK); // Resolve classes used by archived heap objects if (UseSharedSpaces) { - HeapShared::resolve_classes(CHECK); + HeapShared::resolve_classes(THREAD); } } -#ifdef ASSERT -// Verify that this placeholder exists since this class is in the middle of loading. -void verify_placeholder(Symbol* class_name, ClassLoaderData* loader_data) { - // Only parallel capable class loaders use placeholder table for define class. - assert_locked_or_safepoint(SystemDictionary_lock); - unsigned int name_hash = placeholders()->compute_hash(class_name); - Symbol* ph_check = placeholders()->find_entry(name_hash, class_name, loader_data); - assert(ph_check != NULL, "This placeholder should exist"); -} -#endif // ASSERT - // Constraints on class loaders. The details of the algorithm can be // found in the OOPSLA'98 paper "Dynamic Class Loading in the Java // Virtual Machine" by Sheng Liang and Gilad Bracha. The basic idea is @@ -1924,8 +1912,6 @@ void SystemDictionary::check_constraints(unsigned int name_hash, } } - DEBUG_ONLY(if (is_parallelCapable(class_loader)) verify_placeholder(name, loader_data)); - if (throwException == false) { if (constraints()->check_or_update(k, class_loader, name) == false) { throwException = true; diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index 83db92bd3ac..5c73137f64f 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -359,9 +359,6 @@ class SystemDictionary : AllStatic { Handle class_loader, InstanceKlass* k, TRAPS); static InstanceKlass* load_instance_class(Symbol* class_name, Handle class_loader, TRAPS); - static bool is_parallelDefine(Handle class_loader); - static Handle compute_loader_lock_object(Thread* thread, Handle class_loader); - static void check_loader_lock_contention(Thread* thread, Handle loader_lock); static bool is_shared_class_visible(Symbol* class_name, InstanceKlass* ik, PackageEntry* pkg_entry, @@ -397,7 +394,7 @@ class SystemDictionary : AllStatic { static InstanceKlass* load_shared_boot_class(Symbol* class_name, PackageEntry* pkg_entry, TRAPS); - static bool is_parallelCapable(Handle class_loader); + static Handle get_loader_lock_or_null(Handle class_loader); static InstanceKlass* find_or_define_instance_class(Symbol* class_name, Handle class_loader, InstanceKlass* k, TRAPS); diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 4c2dfc3aa2e..643e67d16e0 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -44,6 +44,7 @@ #include "logging/logStream.hpp" #include "memory/allocation.hpp" #include "memory/archiveUtils.hpp" +#include "memory/archiveBuilder.hpp" #include "memory/dynamicArchive.hpp" #include "memory/filemap.hpp" #include "memory/heapShared.hpp" @@ -279,15 +280,6 @@ class DumpTimeSharedClassTable: public ResourceHashtable< }; class LambdaProxyClassKey { - template static void original_to_target(T& field) { - if (field != NULL) { - if (DynamicDumpSharedSpaces) { - field = DynamicArchive::original_to_target(field); - } - ArchivePtrMarker::mark_pointer(&field); - } - } - InstanceKlass* _caller_ik; Symbol* _invoked_name; Symbol* _invoked_type; @@ -318,13 +310,13 @@ class LambdaProxyClassKey { it->push(&_instantiated_method_type); } - void original_to_target() { - original_to_target(_caller_ik); - original_to_target(_instantiated_method_type); - original_to_target(_invoked_name); - original_to_target(_invoked_type); - original_to_target(_member_method); - original_to_target(_method_type); + void mark_pointers() { + ArchivePtrMarker::mark_pointer(&_caller_ik); + ArchivePtrMarker::mark_pointer(&_instantiated_method_type); + ArchivePtrMarker::mark_pointer(&_invoked_name); + ArchivePtrMarker::mark_pointer(&_invoked_type); + ArchivePtrMarker::mark_pointer(&_member_method); + ArchivePtrMarker::mark_pointer(&_method_type); } bool equals(LambdaProxyClassKey const& other) const { @@ -337,11 +329,11 @@ class LambdaProxyClassKey { } unsigned int hash() const { - return SystemDictionaryShared::hash_for_shared_dictionary(_caller_ik) + - SystemDictionaryShared::hash_for_shared_dictionary(_invoked_name) + - SystemDictionaryShared::hash_for_shared_dictionary(_invoked_type) + - SystemDictionaryShared::hash_for_shared_dictionary(_method_type) + - SystemDictionaryShared::hash_for_shared_dictionary(_instantiated_method_type); + return SystemDictionaryShared::hash_for_shared_dictionary((address)_caller_ik) + + SystemDictionaryShared::hash_for_shared_dictionary((address)_invoked_name) + + SystemDictionaryShared::hash_for_shared_dictionary((address)_invoked_type) + + SystemDictionaryShared::hash_for_shared_dictionary((address)_method_type) + + SystemDictionaryShared::hash_for_shared_dictionary((address)_instantiated_method_type); } static unsigned int dumptime_hash(Symbol* sym) { @@ -406,10 +398,8 @@ class RunTimeLambdaProxyClassInfo { } void init(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) { _key = key; - _key.original_to_target(); - _proxy_klass_head = DynamicDumpSharedSpaces ? - DynamicArchive::original_to_target(info._proxy_klasses->at(0)) : - info._proxy_klasses->at(0); + _key.mark_pointers(); + _proxy_klass_head = info._proxy_klasses->at(0); ArchivePtrMarker::mark_pointer(&_proxy_klass_head); } @@ -604,14 +594,9 @@ class RunTimeSharedClassInfo { return loader_constraints() + i; } - static u4 object_delta_u4(Symbol* sym) { - if (DynamicDumpSharedSpaces) { - sym = DynamicArchive::original_to_target(sym); - } - return MetaspaceShared::object_delta_u4(sym); - } - void init(DumpTimeSharedClassInfo& info) { + ArchiveBuilder* builder = ArchiveBuilder::current(); + assert(builder->is_in_buffer_space(info._klass), "must be"); _klass = info._klass; if (!SystemDictionaryShared::is_builtin(_klass)) { CrcInfo* c = crc(); @@ -625,8 +610,8 @@ class RunTimeSharedClassInfo { RTVerifierConstraint* vf_constraints = verifier_constraints(); char* flags = verifier_constraint_flags(); for (i = 0; i < _num_verifier_constraints; i++) { - vf_constraints[i]._name = object_delta_u4(info._verifier_constraints->at(i)._name); - vf_constraints[i]._from_name = object_delta_u4(info._verifier_constraints->at(i)._from_name); + vf_constraints[i]._name = builder->any_to_offset_u4(info._verifier_constraints->at(i)._name); + vf_constraints[i]._from_name = builder->any_to_offset_u4(info._verifier_constraints->at(i)._from_name); } for (i = 0; i < _num_verifier_constraints; i++) { flags[i] = info._verifier_constraint_flags->at(i); @@ -636,7 +621,7 @@ class RunTimeSharedClassInfo { if (_num_loader_constraints > 0) { RTLoaderConstraint* ld_constraints = loader_constraints(); for (i = 0; i < _num_loader_constraints; i++) { - ld_constraints[i]._name = object_delta_u4(info._loader_constraints->at(i)._name); + ld_constraints[i]._name = builder->any_to_offset_u4(info._loader_constraints->at(i)._name); ld_constraints[i]._loader_type1 = info._loader_constraints->at(i)._loader_type1; ld_constraints[i]._loader_type2 = info._loader_constraints->at(i)._loader_type2; } @@ -644,12 +629,8 @@ class RunTimeSharedClassInfo { if (_klass->is_hidden()) { InstanceKlass* n_h = info.nest_host(); - if (DynamicDumpSharedSpaces) { - n_h = DynamicArchive::original_to_target(n_h); - } set_nest_host(n_h); } - _klass = DynamicDumpSharedSpaces ? DynamicArchive::original_to_target(info._klass) : info._klass; ArchivePtrMarker::mark_pointer(&_klass); } @@ -682,13 +663,9 @@ class RunTimeSharedClassInfo { return *info_pointer_addr(klass); } static void set_for(InstanceKlass* klass, RunTimeSharedClassInfo* record) { - if (DynamicDumpSharedSpaces) { - klass = DynamicArchive::original_to_buffer(klass); - *info_pointer_addr(klass) = DynamicArchive::buffer_to_target(record); - } else { - *info_pointer_addr(klass) = record; - } - + assert(ArchiveBuilder::current()->is_in_buffer_space(klass), "must be"); + assert(ArchiveBuilder::current()->is_in_buffer_space(record), "must be"); + *info_pointer_addr(klass) = record; ArchivePtrMarker::mark_pointer(info_pointer_addr(klass)); } @@ -1036,7 +1013,7 @@ InstanceKlass* SystemDictionaryShared::find_or_load_shared_class( // Note: currently, find_or_load_shared_class is called only from // JVM_FindLoadedClass and used for PlatformClassLoader and AppClassLoader, // which are parallel-capable loaders, so a lock here is NOT taken. - assert(is_parallelCapable(class_loader), "ObjectLocker not required"); + assert(get_loader_lock_or_null(class_loader) == NULL, "ObjectLocker not required"); { MutexLocker mu(THREAD, SystemDictionary_lock); InstanceKlass* check = dictionary->find_class(d_hash, name); @@ -2026,11 +2003,27 @@ size_t SystemDictionaryShared::estimate_size_for_archive() { return total_size; } +unsigned int SystemDictionaryShared::hash_for_shared_dictionary(address ptr) { + if (ArchiveBuilder::is_active()) { + uintx offset = ArchiveBuilder::current()->any_to_offset(ptr); + unsigned int hash = primitive_hash(offset); + DEBUG_ONLY({ + if (MetaspaceObj::is_shared((const MetaspaceObj*)ptr)) { + assert(hash == SystemDictionaryShared::hash_for_shared_dictionary_quick(ptr), "must be"); + } + }); + return hash; + } else { + return SystemDictionaryShared::hash_for_shared_dictionary_quick(ptr); + } +} + class CopyLambdaProxyClassInfoToArchive : StackObj { CompactHashtableWriter* _writer; + ArchiveBuilder* _builder; public: CopyLambdaProxyClassInfoToArchive(CompactHashtableWriter* writer) - : _writer(writer) {} + : _writer(writer), _builder(ArchiveBuilder::current()) {} bool do_entry(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) { // In static dump, info._proxy_klasses->at(0) is already relocated to point to the archived class // (not the original class). @@ -2045,12 +2038,10 @@ class CopyLambdaProxyClassInfoToArchive : StackObj { log_info(cds,dynamic)("Archiving hidden %s", info._proxy_klasses->at(0)->external_name()); size_t byte_size = sizeof(RunTimeLambdaProxyClassInfo); RunTimeLambdaProxyClassInfo* runtime_info = - (RunTimeLambdaProxyClassInfo*)MetaspaceShared::read_only_space_alloc(byte_size); + (RunTimeLambdaProxyClassInfo*)ArchiveBuilder::ro_region_alloc(byte_size); runtime_info->init(key, info); - unsigned int hash = runtime_info->hash(); // Fields in runtime_info->_key already point to target space. - u4 delta = DynamicDumpSharedSpaces ? - MetaspaceShared::object_delta_u4((void*)DynamicArchive::buffer_to_target(runtime_info)) : - MetaspaceShared::object_delta_u4((void*)runtime_info); + unsigned int hash = runtime_info->hash(); + u4 delta = _builder->any_to_offset_u4((void*)runtime_info); _writer->add(hash, delta); return true; } @@ -2065,8 +2056,10 @@ class AdjustLambdaProxyClassInfo : StackObj { for (int i = 0; i < len-1; i++) { InstanceKlass* ok0 = info._proxy_klasses->at(i+0); // this is original klass InstanceKlass* ok1 = info._proxy_klasses->at(i+1); // this is original klass - InstanceKlass* bk0 = DynamicDumpSharedSpaces ? DynamicArchive::original_to_buffer(ok0) : ok0; - InstanceKlass* bk1 = DynamicDumpSharedSpaces ? DynamicArchive::original_to_buffer(ok1) : ok1; + assert(ArchiveBuilder::current()->is_in_buffer_space(ok0), "must be"); + assert(ArchiveBuilder::current()->is_in_buffer_space(ok1), "must be"); + InstanceKlass* bk0 = ok0; + InstanceKlass* bk1 = ok1; assert(bk0->next_link() == 0, "must be called after Klass::remove_unshareable_info()"); assert(bk1->next_link() == 0, "must be called after Klass::remove_unshareable_info()"); bk0->set_next_link(bk1); @@ -2074,11 +2067,8 @@ class AdjustLambdaProxyClassInfo : StackObj { ArchivePtrMarker::mark_pointer(bk0->next_link_addr()); } } - if (DynamicDumpSharedSpaces) { - DynamicArchive::original_to_buffer(info._proxy_klasses->at(0))->set_lambda_proxy_is_available(); - } else { - info._proxy_klasses->at(0)->set_lambda_proxy_is_available(); - } + info._proxy_klasses->at(0)->set_lambda_proxy_is_available(); + return true; } }; @@ -2086,30 +2076,23 @@ class AdjustLambdaProxyClassInfo : StackObj { class CopySharedClassInfoToArchive : StackObj { CompactHashtableWriter* _writer; bool _is_builtin; + ArchiveBuilder *_builder; public: CopySharedClassInfoToArchive(CompactHashtableWriter* writer, bool is_builtin) - : _writer(writer), _is_builtin(is_builtin) {} + : _writer(writer), _is_builtin(is_builtin), _builder(ArchiveBuilder::current()) {} bool do_entry(InstanceKlass* k, DumpTimeSharedClassInfo& info) { if (!info.is_excluded() && info.is_builtin() == _is_builtin) { size_t byte_size = RunTimeSharedClassInfo::byte_size(info._klass, info.num_verifier_constraints(), info.num_loader_constraints()); RunTimeSharedClassInfo* record; - record = (RunTimeSharedClassInfo*)MetaspaceShared::read_only_space_alloc(byte_size); + record = (RunTimeSharedClassInfo*)ArchiveBuilder::ro_region_alloc(byte_size); record->init(info); unsigned int hash; Symbol* name = info._klass->name(); - if (DynamicDumpSharedSpaces) { - name = DynamicArchive::original_to_target(name); - } - hash = SystemDictionaryShared::hash_for_shared_dictionary(name); - u4 delta; - if (DynamicDumpSharedSpaces) { - delta = MetaspaceShared::object_delta_u4(DynamicArchive::buffer_to_target(record)); - } else { - delta = MetaspaceShared::object_delta_u4(record); - } + hash = SystemDictionaryShared::hash_for_shared_dictionary((address)name); + u4 delta = _builder->buffer_to_offset_u4((address)record); if (_is_builtin && info._klass->is_hidden()) { // skip } else { @@ -2200,7 +2183,7 @@ SystemDictionaryShared::find_record(RunTimeSharedDictionary* static_dict, RunTim return NULL; } - unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary(name); + unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary_quick(name); const RunTimeSharedClassInfo* record = NULL; if (!MetaspaceShared::is_shared_dynamic(name)) { // The names of all shared classes in the static dict must also be in the diff --git a/src/hotspot/share/classfile/systemDictionaryShared.hpp b/src/hotspot/share/classfile/systemDictionaryShared.hpp index a0b7043077b..37f3d9a33a4 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.hpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP #define SHARE_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP +#include "classfile/classLoaderData.hpp" #include "classfile/packageEntry.hpp" #include "classfile/systemDictionary.hpp" #include "memory/filemap.hpp" @@ -341,12 +342,15 @@ class SystemDictionaryShared: public SystemDictionary { #endif template - static unsigned int hash_for_shared_dictionary(T* ptr) { + static unsigned int hash_for_shared_dictionary_quick(T* ptr) { + assert(MetaspaceObj::is_shared((const MetaspaceObj*)ptr), "must be"); assert(ptr > (T*)SharedBaseAddress, "must be"); - address p = address(ptr) - SharedBaseAddress; - return primitive_hash
(p); + uintx offset = uintx(ptr) - uintx(SharedBaseAddress); + return primitive_hash(offset); } + static unsigned int hash_for_shared_dictionary(address ptr); + #if INCLUDE_CDS_JAVA_HEAP private: static void update_archived_mirror_native_pointers_for(RunTimeSharedDictionary* dict); diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 9ab389d99fd..3d402292fa3 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -36,6 +36,7 @@ #include "code/pcDesc.hpp" #include "compiler/compilationPolicy.hpp" #include "compiler/compileBroker.hpp" +#include "gc/shared/collectedHeap.hpp" #include "jfr/jfrEvents.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" diff --git a/src/hotspot/share/code/compiledIC.cpp b/src/hotspot/share/code/compiledIC.cpp index 6d92de716ff..607266482dd 100644 --- a/src/hotspot/share/code/compiledIC.cpp +++ b/src/hotspot/share/code/compiledIC.cpp @@ -35,11 +35,13 @@ #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" +#include "oops/klass.inline.hpp" #include "oops/method.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "runtime/handles.inline.hpp" #include "runtime/icache.hpp" +#include "runtime/safepoint.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/events.hpp" diff --git a/src/hotspot/share/code/compiledMethod.cpp b/src/hotspot/share/code/compiledMethod.cpp index 9cb3ee80475..734711b2259 100644 --- a/src/hotspot/share/code/compiledMethod.cpp +++ b/src/hotspot/share/code/compiledMethod.cpp @@ -36,6 +36,8 @@ #include "logging/log.hpp" #include "logging/logTag.hpp" #include "memory/resourceArea.hpp" +#include "oops/compiledICHolder.inline.hpp" +#include "oops/klass.inline.hpp" #include "oops/methodData.hpp" #include "oops/method.inline.hpp" #include "prims/methodHandles.hpp" diff --git a/src/hotspot/share/code/debugInfo.cpp b/src/hotspot/share/code/debugInfo.cpp index 8d8b640b843..aeed7f4d937 100644 --- a/src/hotspot/share/code/debugInfo.cpp +++ b/src/hotspot/share/code/debugInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ #include "code/debugInfo.hpp" #include "code/debugInfoRec.hpp" #include "code/nmethod.hpp" +#include "gc/shared/collectedHeap.hpp" #include "memory/universe.hpp" #include "oops/oop.inline.hpp" #include "runtime/handles.inline.hpp" diff --git a/src/hotspot/share/code/dependencies.cpp b/src/hotspot/share/code/dependencies.cpp index 862e673fc5d..d52478adda6 100644 --- a/src/hotspot/share/code/dependencies.cpp +++ b/src/hotspot/share/code/dependencies.cpp @@ -99,32 +99,12 @@ void Dependencies::assert_abstract_with_unique_concrete_subtype(ciKlass* ctxk, c assert_common_2(abstract_with_unique_concrete_subtype, ctxk, conck); } -void Dependencies::assert_abstract_with_no_concrete_subtype(ciKlass* ctxk) { - check_ctxk_abstract(ctxk); - assert_common_1(abstract_with_no_concrete_subtype, ctxk); -} - -void Dependencies::assert_concrete_with_no_concrete_subtype(ciKlass* ctxk) { - check_ctxk_concrete(ctxk); - assert_common_1(concrete_with_no_concrete_subtype, ctxk); -} - void Dependencies::assert_unique_concrete_method(ciKlass* ctxk, ciMethod* uniqm) { check_ctxk(ctxk); check_unique_method(ctxk, uniqm); assert_common_2(unique_concrete_method, ctxk, uniqm); } -void Dependencies::assert_abstract_with_exclusive_concrete_subtypes(ciKlass* ctxk, ciKlass* k1, ciKlass* k2) { - check_ctxk(ctxk); - assert_common_3(abstract_with_exclusive_concrete_subtypes_2, ctxk, k1, k2); -} - -void Dependencies::assert_exclusive_concrete_methods(ciKlass* ctxk, ciMethod* m1, ciMethod* m2) { - check_ctxk(ctxk); - assert_common_3(exclusive_concrete_methods_2, ctxk, m1, m2); -} - void Dependencies::assert_has_no_finalizable_subclasses(ciKlass* ctxk) { check_ctxk(ctxk); assert_common_1(no_finalizable_subclasses, ctxk); @@ -266,47 +246,6 @@ void Dependencies::assert_common_2(DepType dept, deps->append(x1); } -void Dependencies::assert_common_3(DepType dept, - ciKlass* ctxk, ciBaseObject* x, ciBaseObject* x2) { - assert(dep_context_arg(dept) == 0, "sanity"); - assert(dep_args(dept) == 3, "sanity"); - log_dependency(dept, ctxk, x, x2); - GrowableArray* deps = _deps[dept]; - - // try to normalize an unordered pair: - bool swap = false; - switch (dept) { - case abstract_with_exclusive_concrete_subtypes_2: - swap = (x->ident() > x2->ident() && x->as_metadata()->as_klass() != ctxk); - break; - case exclusive_concrete_methods_2: - swap = (x->ident() > x2->ident() && x->as_metadata()->as_method()->holder() != ctxk); - break; - default: - break; - } - if (swap) { ciBaseObject* t = x; x = x2; x2 = t; } - - // see if the same (or a similar) dep is already recorded - if (note_dep_seen(dept, x) && note_dep_seen(dept, x2)) { - // look in this bucket for redundant assertions - const int stride = 3; - for (int i = deps->length(); (i -= stride) >= 0; ) { - ciBaseObject* y = deps->at(i+1); - ciBaseObject* y2 = deps->at(i+2); - if (x == y && x2 == y2) { // same subjects; check the context - if (maybe_merge_ctxk(deps, i+0, ctxk)) { - return; - } - } - } - } - // append the assertion in the correct bucket: - deps->append(ctxk); - deps->append(x); - deps->append(x2); -} - #if INCLUDE_JVMCI bool Dependencies::maybe_merge_ctxk(GrowableArray* deps, int ctxk_i, DepValue ctxk2_dv) { @@ -473,10 +412,7 @@ size_t Dependencies::estimate_size_in_bytes() { ciKlass* Dependencies::ctxk_encoded_as_null(DepType dept, ciBaseObject* x) { switch (dept) { - case abstract_with_exclusive_concrete_subtypes_2: - return x->as_metadata()->as_klass(); case unique_concrete_method: - case exclusive_concrete_methods_2: return x->as_metadata()->as_method()->holder(); default: return NULL; // let NULL be NULL @@ -486,11 +422,7 @@ ciKlass* Dependencies::ctxk_encoded_as_null(DepType dept, ciBaseObject* x) { Klass* Dependencies::ctxk_encoded_as_null(DepType dept, Metadata* x) { assert(must_be_in_vm(), "raw oops here"); switch (dept) { - case abstract_with_exclusive_concrete_subtypes_2: - assert(x->is_klass(), "sanity"); - return (Klass*) x; case unique_concrete_method: - case exclusive_concrete_methods_2: assert(x->is_method(), "sanity"); return ((Method*)x)->method_holder(); default: @@ -593,11 +525,7 @@ const char* Dependencies::_dep_name[TYPE_LIMIT] = { "evol_method", "leaf_type", "abstract_with_unique_concrete_subtype", - "abstract_with_no_concrete_subtype", - "concrete_with_no_concrete_subtype", "unique_concrete_method", - "abstract_with_exclusive_concrete_subtypes_2", - "exclusive_concrete_methods_2", "no_finalizable_subclasses", "call_site_target_value" }; @@ -607,11 +535,7 @@ int Dependencies::_dep_args[TYPE_LIMIT] = { 1, // evol_method m 1, // leaf_type ctxk 2, // abstract_with_unique_concrete_subtype ctxk, k - 1, // abstract_with_no_concrete_subtype ctxk - 1, // concrete_with_no_concrete_subtype ctxk 2, // unique_concrete_method ctxk, m - 3, // unique_concrete_subtypes_2 ctxk, k1, k2 - 3, // unique_concrete_methods_2 ctxk, m1, m2 1, // no_finalizable_subclasses ctxk 2 // call_site_target_value call_site, method_handle }; @@ -1347,8 +1271,8 @@ static bool count_find_witness_calls() { Klass* ClassHierarchyWalker::find_witness_in(KlassDepChange& changes, - Klass* context_type, - bool participants_hide_witnesses) { + Klass* context_type, + bool participants_hide_witnesses) { assert(changes.involves_context(context_type), "irrelevant dependency"); Klass* new_type = changes.new_type(); @@ -1398,8 +1322,8 @@ Klass* ClassHierarchyWalker::find_witness_in(KlassDepChange& changes, // If top_level_call is false, skip testing the context type, // because the caller has already considered it. Klass* ClassHierarchyWalker::find_witness_anywhere(Klass* context_type, - bool participants_hide_witnesses, - bool top_level_call) { + bool participants_hide_witnesses, + bool top_level_call) { // Current thread must be in VM (not native mode, as in CI): assert(must_be_in_vm(), "raw oops here"); // Must not move the class hierarchy during this check: @@ -1498,8 +1422,8 @@ Klass* ClassHierarchyWalker::find_witness_anywhere(Klass* context_type, // since the recursive call sees sub as the context_type.) if (do_counts) { NOT_PRODUCT(deps_find_witness_recursions++); } Klass* witness = find_witness_anywhere(sub, - participants_hide_witnesses, - /*top_level_call=*/ false); + participants_hide_witnesses, + /*top_level_call=*/ false); if (witness != NULL) return witness; } } @@ -1606,32 +1530,12 @@ Klass* Dependencies::check_leaf_type(Klass* ctxk) { // This allows the compiler to narrow occurrences of ctxk by conck, // when dealing with the types of actual instances. Klass* Dependencies::check_abstract_with_unique_concrete_subtype(Klass* ctxk, - Klass* conck, - KlassDepChange* changes) { + Klass* conck, + KlassDepChange* changes) { ClassHierarchyWalker wf(conck); return wf.find_witness_subtype(ctxk, changes); } -// If a non-concrete class has no concrete subtypes, it is not (yet) -// instantiatable. This can allow the compiler to make some paths go -// dead, if they are gated by a test of the type. -Klass* Dependencies::check_abstract_with_no_concrete_subtype(Klass* ctxk, - KlassDepChange* changes) { - // Find any concrete subtype, with no participants: - ClassHierarchyWalker wf; - return wf.find_witness_subtype(ctxk, changes); -} - - -// If a concrete class has no concrete subtypes, it can always be -// exactly typed. This allows the use of a cheaper type test. -Klass* Dependencies::check_concrete_with_no_concrete_subtype(Klass* ctxk, - KlassDepChange* changes) { - // Find any concrete subtype, with only the ctxk as participant: - ClassHierarchyWalker wf(ctxk); - return wf.find_witness_subtype(ctxk, changes); -} - // Find the unique concrete proper subtype of ctxk, or NULL if there // is more than one concrete proper subtype. If there are no concrete @@ -1645,22 +1549,6 @@ Klass* Dependencies::find_unique_concrete_subtype(Klass* ctxk) { if (wit != NULL) return NULL; // Too many witnesses. Klass* conck = wf.participant(0); if (conck == NULL) { -#ifndef PRODUCT - // Make sure the dependency mechanism will pass this discovery: - if (VerifyDependencies) { - // Turn off dependency tracing while actually testing deps. - FlagSetting fs(TraceDependencies, false); - if (!Dependencies::is_concrete_klass(ctxk)) { - guarantee(NULL == - (void *)check_abstract_with_no_concrete_subtype(ctxk), - "verify dep."); - } else { - guarantee(NULL == - (void *)check_concrete_with_no_concrete_subtype(ctxk), - "verify dep."); - } - } -#endif //PRODUCT return ctxk; // Return ctxk as a flag for "no subtypes". } else { #ifndef PRODUCT @@ -1679,76 +1567,12 @@ Klass* Dependencies::find_unique_concrete_subtype(Klass* ctxk) { } } -// Test the assertion that the k[12] are the only concrete subtypes of ctxk, -// except possibly for further subtypes of k[12] themselves. -// The context type must be abstract. The types k1 and k2 are themselves -// allowed to have further concrete subtypes. -Klass* Dependencies::check_abstract_with_exclusive_concrete_subtypes( - Klass* ctxk, - Klass* k1, - Klass* k2, - KlassDepChange* changes) { - ClassHierarchyWalker wf; - wf.add_participant(k1); - wf.add_participant(k2); - return wf.find_witness_subtype(ctxk, changes); -} - -// Search ctxk for concrete implementations. If there are klen or fewer, -// pack them into the given array and return the number. -// Otherwise, return -1, meaning the given array would overflow. -// (Note that a return of 0 means there are exactly no concrete subtypes.) -// In this search, if ctxk is concrete, it will be reported alone. -// For any type CC reported, no proper subtypes of CC will be reported. -int Dependencies::find_exclusive_concrete_subtypes(Klass* ctxk, - int klen, - Klass* karray[]) { - ClassHierarchyWalker wf; - wf.record_witnesses(klen); - Klass* wit = wf.find_witness_subtype(ctxk); - if (wit != NULL) return -1; // Too many witnesses. - int num = wf.num_participants(); - assert(num <= klen, "oob"); - // Pack the result array with the good news. - for (int i = 0; i < num; i++) - karray[i] = wf.participant(i); -#ifndef PRODUCT - // Make sure the dependency mechanism will pass this discovery: - if (VerifyDependencies) { - // Turn off dependency tracing while actually testing deps. - FlagSetting fs(TraceDependencies, false); - switch (Dependencies::is_concrete_klass(ctxk)? -1: num) { - case -1: // ctxk was itself concrete - guarantee(num == 1 && karray[0] == ctxk, "verify dep."); - break; - case 0: - guarantee(NULL == (void *)check_abstract_with_no_concrete_subtype(ctxk), - "verify dep."); - break; - case 1: - guarantee(NULL == (void *) - check_abstract_with_unique_concrete_subtype(ctxk, karray[0]), - "verify dep."); - break; - case 2: - guarantee(NULL == (void *) - check_abstract_with_exclusive_concrete_subtypes(ctxk, - karray[0], - karray[1]), - "verify dep."); - break; - default: - ShouldNotReachHere(); // klen > 2 yet supported - } - } -#endif //PRODUCT - return num; -} // If a class (or interface) has a unique concrete method uniqm, return NULL. // Otherwise, return a class that contains an interfering method. -Klass* Dependencies::check_unique_concrete_method(Klass* ctxk, Method* uniqm, - KlassDepChange* changes) { +Klass* Dependencies::check_unique_concrete_method(Klass* ctxk, + Method* uniqm, + KlassDepChange* changes) { // Here is a missing optimization: If uniqm->is_final(), // we don't really need to search beneath it for overrides. // This is probably not important, since we don't use dependencies @@ -1792,16 +1616,6 @@ Method* Dependencies::find_unique_concrete_method(Klass* ctxk, Method* m) { return fm; } -Klass* Dependencies::check_exclusive_concrete_methods(Klass* ctxk, - Method* m1, - Method* m2, - KlassDepChange* changes) { - ClassHierarchyWalker wf(m1); - wf.add_participant(m1->method_holder()); - wf.add_participant(m2->method_holder()); - return wf.find_witness_definer(ctxk, changes); -} - Klass* Dependencies::check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepChange* changes) { Klass* search_at = ctxk; if (changes != NULL) @@ -1854,21 +1668,9 @@ Klass* Dependencies::DepStream::check_klass_dependency(KlassDepChange* changes) case abstract_with_unique_concrete_subtype: witness = check_abstract_with_unique_concrete_subtype(context_type(), type_argument(1), changes); break; - case abstract_with_no_concrete_subtype: - witness = check_abstract_with_no_concrete_subtype(context_type(), changes); - break; - case concrete_with_no_concrete_subtype: - witness = check_concrete_with_no_concrete_subtype(context_type(), changes); - break; case unique_concrete_method: witness = check_unique_concrete_method(context_type(), method_argument(1), changes); break; - case abstract_with_exclusive_concrete_subtypes_2: - witness = check_abstract_with_exclusive_concrete_subtypes(context_type(), type_argument(1), type_argument(2), changes); - break; - case exclusive_concrete_methods_2: - witness = check_exclusive_concrete_methods(context_type(), method_argument(1), method_argument(2), changes); - break; case no_finalizable_subclasses: witness = check_has_no_finalizable_subclasses(context_type(), changes); break; diff --git a/src/hotspot/share/code/dependencies.hpp b/src/hotspot/share/code/dependencies.hpp index 960be1c3c71..55bbc11502a 100644 --- a/src/hotspot/share/code/dependencies.hpp +++ b/src/hotspot/share/code/dependencies.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,6 +57,7 @@ class nmethod; class OopRecorder; class xmlStream; class CompileLog; +class CompileTask; class DepChange; class KlassDepChange; class CallSiteDepChange; @@ -115,12 +116,6 @@ class Dependencies: public ResourceObj { // An abstract class CX has exactly one concrete subtype CC. abstract_with_unique_concrete_subtype, - // The type CX is purely abstract, with no concrete subtype* at all. - abstract_with_no_concrete_subtype, - - // The concrete CX is free of concrete proper subtypes. - concrete_with_no_concrete_subtype, - // Given a method M1 and a context class CX, the set MM(CX, M1) of // "concrete matching methods" in CX of M1 is the set of every // concrete M2 for which it is possible to create an invokevirtual @@ -139,23 +134,6 @@ class Dependencies: public ResourceObj { // than {M1}. unique_concrete_method, // one unique concrete method under CX - // An "exclusive" assertion concerns two methods or subtypes, and - // declares that there are at most two (or perhaps later N>2) - // specific items that jointly satisfy the restriction. - // We list all items explicitly rather than just giving their - // count, for robustness in the face of complex schema changes. - - // A context class CX (which may be either abstract or concrete) - // has two exclusive concrete subtypes* C1, C2 if every concrete - // subtype* of CX is either C1 or C2. Note that if neither C1 or C2 - // are equal to CX, then CX itself must be abstract. But it is - // also possible (for example) that C1 is CX (a concrete class) - // and C2 is a proper subtype of C1. - abstract_with_exclusive_concrete_subtypes_2, - - // This dependency asserts that MM(CX, M1) is no greater than {M1,M2}. - exclusive_concrete_methods_2, - // This dependency asserts that no instances of class or it's // subclasses require finalization registration. no_finalizable_subclasses, @@ -347,18 +325,13 @@ class Dependencies: public ResourceObj { void assert_common_1(DepType dept, ciBaseObject* x); void assert_common_2(DepType dept, ciBaseObject* x0, ciBaseObject* x1); - void assert_common_3(DepType dept, ciKlass* ctxk, ciBaseObject* x1, ciBaseObject* x2); public: // Adding assertions to a new dependency set at compile time: void assert_evol_method(ciMethod* m); void assert_leaf_type(ciKlass* ctxk); void assert_abstract_with_unique_concrete_subtype(ciKlass* ctxk, ciKlass* conck); - void assert_abstract_with_no_concrete_subtype(ciKlass* ctxk); - void assert_concrete_with_no_concrete_subtype(ciKlass* ctxk); void assert_unique_concrete_method(ciKlass* ctxk, ciMethod* uniqm); - void assert_abstract_with_exclusive_concrete_subtypes(ciKlass* ctxk, ciKlass* k1, ciKlass* k2); - void assert_exclusive_concrete_methods(ciKlass* ctxk, ciMethod* m1, ciMethod* m2); void assert_has_no_finalizable_subclasses(ciKlass* ctxk); void assert_call_site_target_value(ciCallSite* call_site, ciMethodHandle* method_handle); @@ -425,18 +398,8 @@ class Dependencies: public ResourceObj { // Checking old assertions at run-time (in the VM only): static Klass* check_evol_method(Method* m); static Klass* check_leaf_type(Klass* ctxk); - static Klass* check_abstract_with_unique_concrete_subtype(Klass* ctxk, Klass* conck, - KlassDepChange* changes = NULL); - static Klass* check_abstract_with_no_concrete_subtype(Klass* ctxk, - KlassDepChange* changes = NULL); - static Klass* check_concrete_with_no_concrete_subtype(Klass* ctxk, - KlassDepChange* changes = NULL); - static Klass* check_unique_concrete_method(Klass* ctxk, Method* uniqm, - KlassDepChange* changes = NULL); - static Klass* check_abstract_with_exclusive_concrete_subtypes(Klass* ctxk, Klass* k1, Klass* k2, - KlassDepChange* changes = NULL); - static Klass* check_exclusive_concrete_methods(Klass* ctxk, Method* m1, Method* m2, - KlassDepChange* changes = NULL); + static Klass* check_abstract_with_unique_concrete_subtype(Klass* ctxk, Klass* conck, KlassDepChange* changes = NULL); + static Klass* check_unique_concrete_method(Klass* ctxk, Method* uniqm, KlassDepChange* changes = NULL); static Klass* check_has_no_finalizable_subclasses(Klass* ctxk, KlassDepChange* changes = NULL); static Klass* check_call_site_target_value(oop call_site, oop method_handle, CallSiteDepChange* changes = NULL); // A returned Klass* is NULL if the dependency assertion is still @@ -454,9 +417,8 @@ class Dependencies: public ResourceObj { // It is used by DepStream::spot_check_dependency_at. // Detecting possible new assertions: - static Klass* find_unique_concrete_subtype(Klass* ctxk); - static Method* find_unique_concrete_method(Klass* ctxk, Method* m); - static int find_exclusive_concrete_subtypes(Klass* ctxk, int klen, Klass* k[]); + static Klass* find_unique_concrete_subtype(Klass* ctxk); + static Method* find_unique_concrete_method(Klass* ctxk, Method* m); // Create the encoding which will be stored in an nmethod. void encode_content_bytes(); diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index fbc56d7b749..ab2763a43ab 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -38,6 +38,7 @@ #include "compiler/compilerDirectives.hpp" #include "compiler/directivesParser.hpp" #include "compiler/disassembler.hpp" +#include "gc/shared/collectedHeap.hpp" #include "interpreter/bytecode.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" @@ -45,6 +46,7 @@ #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/access.inline.hpp" +#include "oops/klass.inline.hpp" #include "oops/method.inline.hpp" #include "oops/methodData.hpp" #include "oops/oop.inline.hpp" diff --git a/src/hotspot/share/code/oopRecorder.cpp b/src/hotspot/share/code/oopRecorder.cpp index 11154e0b3a2..6e2dbbb2438 100644 --- a/src/hotspot/share/code/oopRecorder.cpp +++ b/src/hotspot/share/code/oopRecorder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "ci/ciInstance.hpp" #include "ci/ciMetadata.hpp" #include "code/oopRecorder.inline.hpp" +#include "gc/shared/collectedHeap.hpp" #include "memory/allocation.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/jniHandles.inline.hpp" diff --git a/src/hotspot/share/compiler/compileTask.cpp b/src/hotspot/share/compiler/compileTask.cpp index d5de61fbf8c..d610d8bdcf8 100644 --- a/src/hotspot/share/compiler/compileTask.cpp +++ b/src/hotspot/share/compiler/compileTask.cpp @@ -31,7 +31,9 @@ #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/resourceArea.hpp" +#include "oops/klass.inline.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/jniHandles.hpp" CompileTask* CompileTask::_task_free_list = NULL; diff --git a/src/hotspot/share/compiler/compilerDefinitions.cpp b/src/hotspot/share/compiler/compilerDefinitions.cpp index 4d056334634..cd29c595e87 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.cpp +++ b/src/hotspot/share/compiler/compilerDefinitions.cpp @@ -80,7 +80,7 @@ bool CompilationModeFlag::initialize() { // Now that the flag is parsed, we can use any methods of CompilerConfig. if (normal()) { - if (CompilerConfig::is_c1_only()) { + if (CompilerConfig::is_c1_simple_only()) { _mode = Mode::QUICK_ONLY; } else if (CompilerConfig::is_c2_or_jvmci_compiler_only()) { _mode = Mode::HIGH_ONLY; diff --git a/src/hotspot/share/compiler/compilerDirectives.hpp b/src/hotspot/share/compiler/compilerDirectives.hpp index 539635a3823..d51aa28e28c 100644 --- a/src/hotspot/share/compiler/compilerDirectives.hpp +++ b/src/hotspot/share/compiler/compilerDirectives.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,6 +78,7 @@ NOT_PRODUCT(cflags(IGVPrintLevel, intx, PrintIdealGraphLevel, IGVPrintLeve #define compilerdirectives_c2_flags(cflags) #endif +class AbstractCompiler; class CompilerDirectives; class DirectiveSet; diff --git a/src/hotspot/share/compiler/compilerThread.cpp b/src/hotspot/share/compiler/compilerThread.cpp new file mode 100644 index 00000000000..94e00083de0 --- /dev/null +++ b/src/hotspot/share/compiler/compilerThread.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "compiler/compileBroker.hpp" +#include "compiler/compileTask.hpp" +#include "compiler/compilerThread.hpp" +#include "runtime/sweeper.hpp" +#include "runtime/thread.inline.hpp" + +// Create a CompilerThread +CompilerThread::CompilerThread(CompileQueue* queue, + CompilerCounters* counters) + : JavaThread(&CompilerThread::thread_entry) { + _env = NULL; + _log = NULL; + _task = NULL; + _queue = queue; + _counters = counters; + _buffer_blob = NULL; + _compiler = NULL; + + // Compiler uses resource area for compilation, let's bias it to mtCompiler + resource_area()->bias_to(mtCompiler); + +#ifndef PRODUCT + _ideal_graph_printer = NULL; +#endif +} + +CompilerThread::~CompilerThread() { + // Delete objects which were allocated on heap. + delete _counters; +} + +void CompilerThread::thread_entry(JavaThread* thread, TRAPS) { + assert(thread->is_Compiler_thread(), "must be compiler thread"); + CompileBroker::compiler_thread_loop(); +} + +bool CompilerThread::can_call_java() const { + return _compiler != NULL && _compiler->is_jvmci(); +} + +// Create sweeper thread +CodeCacheSweeperThread::CodeCacheSweeperThread() +: JavaThread(&CodeCacheSweeperThread::thread_entry) { + _scanned_compiled_method = NULL; +} + +void CodeCacheSweeperThread::thread_entry(JavaThread* thread, TRAPS) { + NMethodSweeper::sweeper_loop(); +} + +void CodeCacheSweeperThread::oops_do_no_frames(OopClosure* f, CodeBlobClosure* cf) { + JavaThread::oops_do_no_frames(f, cf); + if (_scanned_compiled_method != NULL && cf != NULL) { + // Safepoints can occur when the sweeper is scanning an nmethod so + // process it here to make sure it isn't unloaded in the middle of + // a scan. + cf->do_code_blob(_scanned_compiled_method); + } +} + +void CodeCacheSweeperThread::nmethods_do(CodeBlobClosure* cf) { + JavaThread::nmethods_do(cf); + if (_scanned_compiled_method != NULL && cf != NULL) { + // Safepoints can occur when the sweeper is scanning an nmethod so + // process it here to make sure it isn't unloaded in the middle of + // a scan. + cf->do_code_blob(_scanned_compiled_method); + } +} + diff --git a/src/hotspot/share/compiler/compilerThread.hpp b/src/hotspot/share/compiler/compilerThread.hpp new file mode 100644 index 00000000000..3e0147d28be --- /dev/null +++ b/src/hotspot/share/compiler/compilerThread.hpp @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_COMPILER_COMPILERTHREAD_HPP +#define SHARE_COMPILER_COMPILERTHREAD_HPP + +#include "runtime/thread.hpp" + +class BufferBlob; +class AbstractCompiler; +class ciEnv; +class CompileThread; +class CompileLog; +class CompileTask; +class CompileQueue; +class CompilerCounters; +class IdealGraphPrinter; +class JVMCIEnv; +class JVMCIPrimitiveArray; + +// A thread used for Compilation. +class CompilerThread : public JavaThread { + friend class VMStructs; + private: + CompilerCounters* _counters; + + ciEnv* _env; + CompileLog* _log; + CompileTask* volatile _task; // print_threads_compiling can read this concurrently. + CompileQueue* _queue; + BufferBlob* _buffer_blob; + + AbstractCompiler* _compiler; + TimeStamp _idle_time; + + public: + + static CompilerThread* current(); + + CompilerThread(CompileQueue* queue, CompilerCounters* counters); + ~CompilerThread(); + + bool is_Compiler_thread() const { return true; } + + virtual bool can_call_java() const; + + // Hide native compiler threads from external view. + bool is_hidden_from_external_view() const { return !can_call_java(); } + + void set_compiler(AbstractCompiler* c) { _compiler = c; } + AbstractCompiler* compiler() const { return _compiler; } + + CompileQueue* queue() const { return _queue; } + CompilerCounters* counters() const { return _counters; } + + // Get/set the thread's compilation environment. + ciEnv* env() { return _env; } + void set_env(ciEnv* env) { _env = env; } + + BufferBlob* get_buffer_blob() const { return _buffer_blob; } + void set_buffer_blob(BufferBlob* b) { _buffer_blob = b; } + + // Get/set the thread's logging information + CompileLog* log() { return _log; } + void init_log(CompileLog* log) { + // Set once, for good. + assert(_log == NULL, "set only once"); + _log = log; + } + + void start_idle_timer() { _idle_time.update(); } + jlong idle_time_millis() { + return TimeHelper::counter_to_millis(_idle_time.ticks_since_update()); + } + +#ifndef PRODUCT + private: + IdealGraphPrinter *_ideal_graph_printer; + public: + IdealGraphPrinter *ideal_graph_printer() { return _ideal_graph_printer; } + void set_ideal_graph_printer(IdealGraphPrinter *n) { _ideal_graph_printer = n; } +#endif + + // Get/set the thread's current task + CompileTask* task() { return _task; } + void set_task(CompileTask* task) { _task = task; } + + static void thread_entry(JavaThread* thread, TRAPS); +}; + +inline CompilerThread* JavaThread::as_CompilerThread() { + assert(is_Compiler_thread(), "just checking"); + return (CompilerThread*)this; +} + +inline CompilerThread* CompilerThread::current() { + return JavaThread::current()->as_CompilerThread(); +} + +// Dedicated thread to sweep the code cache +class CodeCacheSweeperThread : public JavaThread { + CompiledMethod* _scanned_compiled_method; // nmethod being scanned by the sweeper + + static void thread_entry(JavaThread* thread, TRAPS); + + public: + CodeCacheSweeperThread(); + // Track the nmethod currently being scanned by the sweeper + void set_scanned_compiled_method(CompiledMethod* cm) { + assert(_scanned_compiled_method == NULL || cm == NULL, "should reset to NULL before writing a new value"); + _scanned_compiled_method = cm; + } + + // Hide sweeper thread from external view. + bool is_hidden_from_external_view() const { return true; } + + bool is_Code_cache_sweeper_thread() const { return true; } + + // Prevent GC from unloading _scanned_compiled_method + void oops_do_no_frames(OopClosure* f, CodeBlobClosure* cf); + void nmethods_do(CodeBlobClosure* cf); +}; + + +#endif // SHARE_COMPILER_COMPILERTHREAD_HPP diff --git a/src/hotspot/share/gc/g1/g1BarrierSet.hpp b/src/hotspot/share/gc/g1/g1BarrierSet.hpp index 9b7ee9e93e7..8d009a9e19f 100644 --- a/src/hotspot/share/gc/g1/g1BarrierSet.hpp +++ b/src/hotspot/share/gc/g1/g1BarrierSet.hpp @@ -53,6 +53,10 @@ class G1BarrierSet: public CardTableBarrierSet { G1BarrierSet(G1CardTable* table); ~G1BarrierSet() { } + virtual bool card_mark_must_follow_store() const { + return true; + } + // Add "pre_val" to a set of objects that may have been disconnected from the // pre-marking object graph. static void enqueue(oop pre_val); diff --git a/src/hotspot/share/gc/g1/g1CardTable.hpp b/src/hotspot/share/gc/g1/g1CardTable.hpp index 3540bb9411a..925ae098b63 100644 --- a/src/hotspot/share/gc/g1/g1CardTable.hpp +++ b/src/hotspot/share/gc/g1/g1CardTable.hpp @@ -79,7 +79,7 @@ class G1CardTable : public CardTable { STATIC_ASSERT(BitsPerByte == 8); static const size_t WordAlreadyScanned = (SIZE_MAX / 255) * g1_card_already_scanned; - G1CardTable(MemRegion whole_heap): CardTable(whole_heap, /* scanned concurrently */ true), _listener() { + G1CardTable(MemRegion whole_heap): CardTable(whole_heap), _listener() { _listener.set_card_table(this); } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 8f33eac4443..2b97e7f7a1a 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1497,8 +1497,8 @@ G1RegionToSpaceMapper* G1CollectedHeap::create_aux_memory_mapper(const char* des os::trace_page_sizes_for_requested_size(description, size, - preferred_page_size, page_size, + preferred_page_size, rs.base(), rs.size()); diff --git a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp index 75d8f656305..75592996898 100644 --- a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #ifndef SHARE_GC_G1_G1FULLGCMARKER_INLINE_HPP #define SHARE_GC_G1_G1FULLGCMARKER_INLINE_HPP +#include "classfile/classLoaderData.hpp" #include "classfile/javaClasses.inline.hpp" #include "gc/g1/g1Allocator.inline.hpp" #include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp" diff --git a/src/hotspot/share/gc/g1/g1OopClosures.hpp b/src/hotspot/share/gc/g1/g1OopClosures.hpp index ae967681c18..8c77363031b 100644 --- a/src/hotspot/share/gc/g1/g1OopClosures.hpp +++ b/src/hotspot/share/gc/g1/g1OopClosures.hpp @@ -156,13 +156,7 @@ enum G1Barrier { G1BarrierNoOptRoots // Do not collect optional roots. }; -enum G1Mark { - G1MarkNone, - G1MarkFromRoot, - G1MarkPromotedFromRoot -}; - -template +template class G1ParCopyClosure : public G1ParCopyHelper { public: G1ParCopyClosure(G1CollectedHeap* g1h, G1ParScanThreadState* par_scan_state) : diff --git a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp index 012f6d8a8b2..78fdf820707 100644 --- a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp +++ b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp @@ -215,9 +215,9 @@ void G1ParCopyHelper::trim_queue_partially() { _par_scan_state->trim_queue_partially(); } -template +template template -void G1ParCopyClosure::do_oop_work(T* p) { +void G1ParCopyClosure::do_oop_work(T* p) { T heap_oop = RawAccess<>::oop_load(p); if (CompressedOops::is_null(heap_oop)) { @@ -250,9 +250,10 @@ void G1ParCopyClosure::do_oop_work(T* p) { _par_scan_state->remember_root_into_optional_region(p); } - // The object is not in collection set. If we're a root scanning - // closure during a concurrent start pause then attempt to mark the object. - if (do_mark_object == G1MarkFromRoot) { + // The object is not in the collection set. should_mark is true iff the + // current closure is applied on strong roots (and weak roots when class + // unloading is disabled) in a concurrent mark start pause. + if (should_mark) { mark_object(obj); } } diff --git a/src/hotspot/share/gc/g1/g1RootClosures.cpp b/src/hotspot/share/gc/g1/g1RootClosures.cpp index 0e8b653232e..1fedd89d278 100644 --- a/src/hotspot/share/gc/g1/g1RootClosures.cpp +++ b/src/hotspot/share/gc/g1/g1RootClosures.cpp @@ -29,7 +29,7 @@ // Closures used for standard G1 evacuation. class G1EvacuationClosures : public G1EvacuationRootClosures { - G1SharedClosures _closures; + G1SharedClosures _closures; public: G1EvacuationClosures(G1CollectedHeap* g1h, @@ -50,10 +50,10 @@ class G1EvacuationClosures : public G1EvacuationRootClosures { // Closures used during concurrent start. // The treatment of "weak" roots is selectable through the template parameter, // this is usually used to control unloading of classes and interned strings. -template +template class G1ConcurrentStartMarkClosures : public G1EvacuationRootClosures { - G1SharedClosures _strong; - G1SharedClosures _weak; + G1SharedClosures _strong; + G1SharedClosures _weak; public: G1ConcurrentStartMarkClosures(G1CollectedHeap* g1h, @@ -75,9 +75,9 @@ G1EvacuationRootClosures* G1EvacuationRootClosures::create_root_closures(G1ParSc G1EvacuationRootClosures* res = NULL; if (g1h->collector_state()->in_concurrent_start_gc()) { if (ClassUnloadingWithConcurrentMark) { - res = new G1ConcurrentStartMarkClosures(g1h, pss); + res = new G1ConcurrentStartMarkClosures(g1h, pss); } else { - res = new G1ConcurrentStartMarkClosures(g1h, pss); + res = new G1ConcurrentStartMarkClosures(g1h, pss); } } else { res = new G1EvacuationClosures(g1h, pss, g1h->collector_state()->in_young_only_phase()); diff --git a/src/hotspot/share/gc/g1/g1RootProcessor.cpp b/src/hotspot/share/gc/g1/g1RootProcessor.cpp index 8ed58797955..93a45b9ffae 100644 --- a/src/hotspot/share/gc/g1/g1RootProcessor.cpp +++ b/src/hotspot/share/gc/g1/g1RootProcessor.cpp @@ -75,7 +75,7 @@ void G1RootProcessor::evacuate_roots(G1ParScanThreadState* pss, uint worker_id) } // CodeCache is already processed in java roots - _process_strong_tasks.all_tasks_completed(n_workers(), G1RP_PS_CodeCache_oops_do); + _process_strong_tasks.all_tasks_claimed(G1RP_PS_CodeCache_oops_do); } // Adaptor to pass the closures to the strong roots in the VM. @@ -106,9 +106,8 @@ void G1RootProcessor::process_strong_roots(OopClosure* oops, // CodeCache is already processed in java roots // refProcessor is not needed since we are inside a safe point - _process_strong_tasks.all_tasks_completed(n_workers(), - G1RP_PS_CodeCache_oops_do, - G1RP_PS_refProcessor_oops_do); + _process_strong_tasks.all_tasks_claimed(G1RP_PS_CodeCache_oops_do, + G1RP_PS_refProcessor_oops_do); } // Adaptor to pass the closures to all the roots in the VM. @@ -144,7 +143,7 @@ void G1RootProcessor::process_all_roots(OopClosure* oops, process_code_cache_roots(blobs, NULL, 0); // refProcessor is not needed since we are inside a safe point - _process_strong_tasks.all_tasks_completed(n_workers(), G1RP_PS_refProcessor_oops_do); + _process_strong_tasks.all_tasks_claimed(G1RP_PS_refProcessor_oops_do); } void G1RootProcessor::process_java_roots(G1RootClosures* closures, diff --git a/src/hotspot/share/gc/g1/g1SharedClosures.hpp b/src/hotspot/share/gc/g1/g1SharedClosures.hpp index 33c2bd1a7ef..55b9a1e62c5 100644 --- a/src/hotspot/share/gc/g1/g1SharedClosures.hpp +++ b/src/hotspot/share/gc/g1/g1SharedClosures.hpp @@ -30,16 +30,11 @@ class G1CollectedHeap; class G1ParScanThreadState; // Simple holder object for a complete set of closures used by the G1 evacuation code. -template +template class G1SharedClosures { - static bool needs_strong_processing() { - // Request strong code root processing when G1MarkFromRoot is passed in during - // concurrent start. - return Mark == G1MarkFromRoot; - } public: - G1ParCopyClosure _oops; - G1ParCopyClosure _oops_in_cld; + G1ParCopyClosure _oops; + G1ParCopyClosure _oops_in_cld; // We do not need (and actually should not) collect oops from nmethods into the // optional collection set as we already automatically collect the corresponding // nmethods in the region's strong code roots set. So set G1BarrierNoOptRoots in @@ -47,7 +42,7 @@ class G1SharedClosures { // If these were present there would be opportunity for multiple threads to try // to change this oop* at the same time. Since embedded oops are not necessarily // word-aligned, this could lead to word tearing during update and crashes. - G1ParCopyClosure _oops_in_nmethod; + G1ParCopyClosure _oops_in_nmethod; G1CLDScanClosure _clds; G1CodeBlobClosure _codeblobs; @@ -57,5 +52,5 @@ class G1SharedClosures { _oops_in_cld(g1h, pss), _oops_in_nmethod(g1h, pss), _clds(&_oops_in_cld, process_only_dirty), - _codeblobs(pss->worker_id(), &_oops_in_nmethod, needs_strong_processing()) {} + _codeblobs(pss->worker_id(), &_oops_in_nmethod, should_mark) {} }; diff --git a/src/hotspot/share/gc/parallel/mutableSpace.cpp b/src/hotspot/share/gc/parallel/mutableSpace.cpp index e0748fe85bc..defb1ffd04e 100644 --- a/src/hotspot/share/gc/parallel/mutableSpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableSpace.cpp @@ -133,7 +133,11 @@ void MutableSpace::initialize(MemRegion mr, } set_bottom(mr.start()); - set_end(mr.end()); + // When expanding concurrently with callers of cas_allocate, setting end + // makes the new space available for allocation by other threads. So this + // assignment must follow all other configuration and initialization that + // might be done for expansion. + Atomic::release_store(end_addr(), mr.end()); if (clear_space) { clear(mangle_space); @@ -211,6 +215,15 @@ bool MutableSpace::cas_deallocate(HeapWord *obj, size_t size) { return Atomic::cmpxchg(top_addr(), expected_top, obj) == expected_top; } +// Only used by oldgen allocation. +bool MutableSpace::needs_expand(size_t word_size) const { + assert_lock_strong(ExpandHeap_lock); + // Holding the lock means end is stable. So while top may be advancing + // via concurrent allocations, there is no need to order the reads of top + // and end here, unlike in cas_allocate. + return pointer_delta(end(), top()) < word_size; +} + void MutableSpace::oop_iterate(OopIterateClosure* cl) { HeapWord* obj_addr = bottom(); HeapWord* t = top(); diff --git a/src/hotspot/share/gc/parallel/mutableSpace.hpp b/src/hotspot/share/gc/parallel/mutableSpace.hpp index 3e9b0a1514c..b6bb131828f 100644 --- a/src/hotspot/share/gc/parallel/mutableSpace.hpp +++ b/src/hotspot/share/gc/parallel/mutableSpace.hpp @@ -142,6 +142,11 @@ class MutableSpace: public CHeapObj { virtual HeapWord* cas_allocate(size_t word_size); // Optional deallocation. Used in NUMA-allocator. bool cas_deallocate(HeapWord *obj, size_t size); + // Return true if this space needs to be expanded in order to satisfy an + // allocation request of the indicated size. Concurrent allocations and + // resizes may change the result of a later call. Used by oldgen allocator. + // precondition: holding ExpandHeap_lock + bool needs_expand(size_t word_size) const; // Iteration. void oop_iterate(OopIterateClosure* cl); diff --git a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp index f26992f4120..d08762b2ca1 100644 --- a/src/hotspot/share/gc/parallel/parMarkBitMap.cpp +++ b/src/hotspot/share/gc/parallel/parMarkBitMap.cpp @@ -50,7 +50,8 @@ ParMarkBitMap::initialize(MemRegion covered_region) const size_t rs_align = page_sz == (size_t) os::vm_page_size() ? 0 : MAX2(page_sz, granularity); ReservedSpace rs(_reserved_byte_size, rs_align, rs_align > 0); - os::trace_page_sizes("Mark Bitmap", raw_bytes, raw_bytes, page_sz, + const size_t used_page_sz = ReservedSpace::actual_reserved_page_size(rs); + os::trace_page_sizes("Mark Bitmap", raw_bytes, raw_bytes, used_page_sz, rs.base(), rs.size()); MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); diff --git a/src/hotspot/share/gc/parallel/psCardTable.hpp b/src/hotspot/share/gc/parallel/psCardTable.hpp index df1e0158727..d912c656741 100644 --- a/src/hotspot/share/gc/parallel/psCardTable.hpp +++ b/src/hotspot/share/gc/parallel/psCardTable.hpp @@ -51,7 +51,7 @@ class PSCardTable: public CardTable { }; public: - PSCardTable(MemRegion whole_heap) : CardTable(whole_heap, /* scanned_concurrently */ false) {} + PSCardTable(MemRegion whole_heap) : CardTable(whole_heap) {} static CardValue youngergen_card_val() { return youngergen_card; } static CardValue verify_card_val() { return verify_card; } diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp index 03ce090a4f4..a0df3dade2a 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #ifndef SHARE_GC_PARALLEL_PSCOMPACTIONMANAGER_INLINE_HPP #define SHARE_GC_PARALLEL_PSCOMPACTIONMANAGER_INLINE_HPP +#include "classfile/classLoaderData.hpp" #include "classfile/javaClasses.inline.hpp" #include "gc/parallel/parMarkBitMap.hpp" #include "gc/parallel/psCompactionManager.hpp" diff --git a/src/hotspot/share/gc/parallel/psOldGen.cpp b/src/hotspot/share/gc/parallel/psOldGen.cpp index 187922d7e14..44c7901571a 100644 --- a/src/hotspot/share/gc/parallel/psOldGen.cpp +++ b/src/hotspot/share/gc/parallel/psOldGen.cpp @@ -35,7 +35,6 @@ #include "logging/log.hpp" #include "oops/oop.inline.hpp" #include "runtime/java.hpp" -#include "runtime/orderAccess.hpp" #include "utilities/align.hpp" PSOldGen::PSOldGen(ReservedSpace rs, size_t initial_size, size_t min_size, @@ -179,19 +178,31 @@ void PSOldGen::object_iterate_block(ObjectClosure* cl, size_t block_index) { } } -HeapWord* PSOldGen::expand_and_cas_allocate(size_t word_size) { - expand(word_size*HeapWordSize); +bool PSOldGen::expand_for_allocate(size_t word_size) { + assert(word_size > 0, "allocating zero words?"); + bool result = true; + { + MutexLocker x(ExpandHeap_lock); + // Avoid "expand storms" by rechecking available space after obtaining + // the lock, because another thread may have already made sufficient + // space available. If insufficient space available, that will remain + // true until we expand, since we have the lock. Other threads may take + // the space we need before we can allocate it, regardless of whether we + // expand. That's okay, we'll just try expanding again. + if (object_space()->needs_expand(word_size)) { + result = expand(word_size*HeapWordSize); + } + } if (GCExpandToAllocateDelayMillis > 0) { os::naked_sleep(GCExpandToAllocateDelayMillis); } - return cas_allocate_noexpand(word_size); + return result; } -void PSOldGen::expand(size_t bytes) { - if (bytes == 0) { - return; - } - MutexLocker x(ExpandHeap_lock); +bool PSOldGen::expand(size_t bytes) { + assert_lock_strong(ExpandHeap_lock); + assert_locked_or_safepoint(Heap_lock); + assert(bytes > 0, "precondition"); const size_t alignment = virtual_space()->alignment(); size_t aligned_bytes = align_up(bytes, alignment); size_t aligned_expand_bytes = align_up(MinHeapDeltaBytes, alignment); @@ -201,13 +212,11 @@ void PSOldGen::expand(size_t bytes) { // providing a page per lgroup. Alignment is larger or equal to the page size. aligned_expand_bytes = MAX2(aligned_expand_bytes, alignment * os::numa_get_groups_num()); } - if (aligned_bytes == 0){ - // The alignment caused the number of bytes to wrap. An expand_by(0) will - // return true with the implication that and expansion was done when it - // was not. A call to expand implies a best effort to expand by "bytes" - // but not a guarantee. Align down to give a best effort. This is likely - // the most that the generation can expand since it has some capacity to - // start with. + if (aligned_bytes == 0) { + // The alignment caused the number of bytes to wrap. A call to expand + // implies a best effort to expand by "bytes" but not a guarantee. Align + // down to give a best effort. This is likely the most that the generation + // can expand since it has some capacity to start with. aligned_bytes = align_down(bytes, alignment); } @@ -225,14 +234,13 @@ void PSOldGen::expand(size_t bytes) { if (success && GCLocker::is_active_and_needs_gc()) { log_debug(gc)("Garbage collection disabled, expanded heap instead"); } + return success; } bool PSOldGen::expand_by(size_t bytes) { assert_lock_strong(ExpandHeap_lock); assert_locked_or_safepoint(Heap_lock); - if (bytes == 0) { - return true; // That's what virtual_space()->expand_by(0) would return - } + assert(bytes > 0, "precondition"); bool result = virtual_space()->expand_by(bytes); if (result) { if (ZapUnusedHeapArea) { @@ -269,7 +277,7 @@ bool PSOldGen::expand_to_reserved() { assert_lock_strong(ExpandHeap_lock); assert_locked_or_safepoint(Heap_lock); - bool result = true; + bool result = false; const size_t remaining_bytes = virtual_space()->uncommitted_size(); if (remaining_bytes > 0) { result = expand_by(remaining_bytes); @@ -324,10 +332,10 @@ void PSOldGen::resize(size_t desired_free_space) { } if (new_size > current_size) { size_t change_bytes = new_size - current_size; + MutexLocker x(ExpandHeap_lock); expand(change_bytes); } else { size_t change_bytes = current_size - new_size; - // shrink doesn't grab this lock, expand does. Is that right? MutexLocker x(ExpandHeap_lock); shrink(change_bytes); } @@ -354,9 +362,9 @@ void PSOldGen::post_resize() { WorkGang* workers = Thread::current()->is_VM_thread() ? &ParallelScavengeHeap::heap()->workers() : NULL; - // Ensure the space bounds are updated and made visible to other - // threads after the other data structures have been resized. - OrderAccess::storestore(); + // The update of the space's end is done by this call. As that + // makes the new space available for concurrent allocation, this + // must be the last step when expanding. object_space()->initialize(new_memregion, SpaceDecorator::DontClear, SpaceDecorator::DontMangle, diff --git a/src/hotspot/share/gc/parallel/psOldGen.hpp b/src/hotspot/share/gc/parallel/psOldGen.hpp index dd0e7fe1e83..53947a94898 100644 --- a/src/hotspot/share/gc/parallel/psOldGen.hpp +++ b/src/hotspot/share/gc/parallel/psOldGen.hpp @@ -79,8 +79,8 @@ class PSOldGen : public CHeapObj { return res; } - HeapWord* expand_and_cas_allocate(size_t word_size); - void expand(size_t bytes); + bool expand_for_allocate(size_t word_size); + bool expand(size_t bytes); bool expand_by(size_t bytes); bool expand_to_reserved(); @@ -135,8 +135,12 @@ class PSOldGen : public CHeapObj { void resize(size_t desired_free_space); HeapWord* allocate(size_t word_size) { - HeapWord* res = cas_allocate_noexpand(word_size); - return (res == NULL) ? expand_and_cas_allocate(word_size) : res; + HeapWord* res; + do { + res = cas_allocate_noexpand(word_size); + // Retry failed allocation if expand succeeds. + } while ((res == nullptr) && expand_for_allocate(word_size)); + return res; } // Iteration. diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 06163a79b70..b606e7080cf 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -556,8 +556,6 @@ void DefNewGeneration::collect(bool full, // The preserved marks should be empty at the start of the GC. _preserved_marks_set.init(1); - heap->rem_set()->prepare_for_younger_refs_iterate(false); - assert(heap->no_allocs_since_save_marks(), "save marks have not been newly set."); diff --git a/src/hotspot/share/gc/serial/defNewGeneration.inline.hpp b/src/hotspot/share/gc/serial/defNewGeneration.inline.hpp index 67dce43e7b6..f3a3079f068 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.inline.hpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.inline.hpp @@ -61,8 +61,7 @@ inline void DefNewGeneration::KeepAliveClosure::do_oop_work(T* p) { // dirty cards in the young gen are never scanned, so the // extra check probably isn't worthwhile. if (GenCollectedHeap::heap()->is_in_reserved(p)) { - oop obj = RawAccess::oop_load(p); - _rs->inline_write_ref_field_gc(p, obj); + _rs->inline_write_ref_field_gc(p); } } @@ -84,7 +83,7 @@ inline void DefNewGeneration::FastKeepAliveClosure::do_oop_work(T* p) { // generation pointer. oop obj = RawAccess::oop_load(p); if ((cast_from_oop(obj) < _boundary) && GenCollectedHeap::heap()->is_in_reserved(p)) { - _rs->inline_write_ref_field_gc(p, obj); + _rs->inline_write_ref_field_gc(p); } } diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp index 2eb39ca3612..d9a8812d580 100644 --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,6 +97,5 @@ void SerialHeap::young_process_roots(OopIterateClosure* root_closure, process_roots(SO_ScavengeCodeCache, root_closure, cld_closure, cld_closure, &mark_code_closure); - rem_set()->at_younger_refs_iterate(); old_gen()->younger_refs_iterate(old_gen_closure); } diff --git a/src/hotspot/share/gc/shared/barrierSet.inline.hpp b/src/hotspot/share/gc/shared/barrierSet.inline.hpp index abbcd5e58d4..4a21c3151c8 100644 --- a/src/hotspot/share/gc/shared/barrierSet.inline.hpp +++ b/src/hotspot/share/gc/shared/barrierSet.inline.hpp @@ -30,6 +30,7 @@ #include "oops/compressedOops.inline.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/oop.hpp" +#include "runtime/thread.hpp" template template diff --git a/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp b/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp index 106412d90b4..a89b57d8e45 100644 --- a/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp +++ b/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp @@ -83,9 +83,6 @@ void CardTableBarrierSetC1::post_barrier(LIRAccess& access, LIR_OprDesc* addr, L LIR_Opr dirty = LIR_OprFact::intConst(CardTable::dirty_card_val()); if (UseCondCardMark) { LIR_Opr cur_value = gen->new_register(T_INT); - if (ct->scanned_concurrently()) { - __ membar_storeload(); - } __ move(card_addr, cur_value); LabelObj* L_already_dirty = new LabelObj(); @@ -94,9 +91,6 @@ void CardTableBarrierSetC1::post_barrier(LIRAccess& access, LIR_OprDesc* addr, L __ move(dirty, card_addr); __ branch_destination(L_already_dirty->label()); } else { - if (ct->scanned_concurrently()) { - __ membar_storestore(); - } __ move(dirty, card_addr); } #endif diff --git a/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp index 3830ef714fd..5743da41c1c 100644 --- a/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/cardTableBarrierSetC2.cpp @@ -58,8 +58,6 @@ void CardTableBarrierSetC2::post_barrier(GraphKit* kit, Node* val, BasicType bt, bool use_precise) const { - CardTableBarrierSet* ctbs = barrier_set_cast(BarrierSet::barrier_set()); - CardTable* ct = ctbs->card_table(); // No store check needed if we're storing a NULL or an old object // (latter case is probably a string constant). The concurrent // mark sweep garbage collector, however, needs to have all nonNull @@ -105,10 +103,6 @@ void CardTableBarrierSetC2::post_barrier(GraphKit* kit, Node* zero = __ ConI(0); // Dirty card value if (UseCondCardMark) { - if (ct->scanned_concurrently()) { - kit->insert_mem_bar(Op_MemBarVolatile, oop_store); - __ sync_kit(kit); - } // The classic GC reference write barrier is typically implemented // as a store into the global card mark table. Unfortunately // unconditional stores can result in false sharing and excessive @@ -121,12 +115,7 @@ void CardTableBarrierSetC2::post_barrier(GraphKit* kit, } // Smash zero into card - if(!ct->scanned_concurrently()) { - __ store(__ ctrl(), card_adr, zero, T_BYTE, adr_type, MemNode::unordered); - } else { - // Specialized path for CM store barrier - __ storeCM(__ ctrl(), card_adr, zero, oop_store, adr_idx, T_BYTE, adr_type); - } + __ store(__ ctrl(), card_adr, zero, T_BYTE, adr_type, MemNode::unordered); if (UseCondCardMark) { __ end_if(); diff --git a/src/hotspot/share/gc/shared/cardGeneration.cpp b/src/hotspot/share/gc/shared/cardGeneration.cpp index f676b84fcb3..6bc6e93809e 100644 --- a/src/hotspot/share/gc/shared/cardGeneration.cpp +++ b/src/hotspot/share/gc/shared/cardGeneration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -309,7 +309,7 @@ void CardGeneration::space_iterate(SpaceClosure* blk, void CardGeneration::younger_refs_iterate(OopIterateClosure* blk) { // Apply "cl->do_oop" to (the address of) (exactly) all the ref fields in - // "sp" that point into younger generations. + // "sp" that point into the young generation. // The iteration is only over objects allocated at the start of the // iterations; objects allocated as a result of applying the closure are // not included. diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index b2a7118e8aa..84f624b3001 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -41,8 +41,7 @@ size_t CardTable::compute_byte_map_size() { return align_up(_guard_index + 1, MAX2(_page_size, granularity)); } -CardTable::CardTable(MemRegion whole_heap, bool conc_scan) : - _scanned_concurrently(conc_scan), +CardTable::CardTable(MemRegion whole_heap) : _whole_heap(whole_heap), _guard_index(0), _last_valid_index(0), diff --git a/src/hotspot/share/gc/shared/cardTable.hpp b/src/hotspot/share/gc/shared/cardTable.hpp index f5b06ebb172..ff406eee4be 100644 --- a/src/hotspot/share/gc/shared/cardTable.hpp +++ b/src/hotspot/share/gc/shared/cardTable.hpp @@ -43,7 +43,6 @@ class CardTable: public CHeapObj { protected: // The declaration order of these const fields is important; see the // constructor before changing. - const bool _scanned_concurrently; const MemRegion _whole_heap; // the region covered by the card table size_t _guard_index; // index of very last element in the card // table; it is set to a guard value @@ -113,7 +112,7 @@ class CardTable: public CHeapObj { static const intptr_t clean_card_row = (intptr_t)(-1); public: - CardTable(MemRegion whole_heap, bool conc_scan); + CardTable(MemRegion whole_heap); virtual ~CardTable(); virtual void initialize(); @@ -245,7 +244,6 @@ class CardTable: public CHeapObj { // But since the heap starts at some higher address, this points to somewhere // before the beginning of the actual _byte_map. CardValue* byte_map_base() const { return _byte_map_base; } - bool scanned_concurrently() const { return _scanned_concurrently; } virtual bool is_in_young(oop obj) const = 0; diff --git a/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp b/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp index 7e491c36dd5..225fca264bd 100644 --- a/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp +++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp @@ -192,5 +192,5 @@ void CardTableBarrierSet::on_thread_detach(Thread* thread) { } bool CardTableBarrierSet::card_mark_must_follow_store() const { - return _card_table->scanned_concurrently(); + return false; } diff --git a/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp b/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp index f88a0dc070a..97e3c4593df 100644 --- a/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp @@ -32,12 +32,7 @@ template inline void CardTableBarrierSet::write_ref_field_post(T* field, oop newVal) { volatile CardValue* byte = _card_table->byte_for(field); - if (_card_table->scanned_concurrently()) { - // Perform a releasing store if the card table is scanned concurrently - Atomic::release_store(byte, CardTable::dirty_card_val()); - } else { - *byte = CardTable::dirty_card_val(); - } + *byte = CardTable::dirty_card_val(); } #endif // SHARE_GC_SHARED_CARDTABLEBARRIERSET_INLINE_HPP diff --git a/src/hotspot/share/gc/shared/cardTableRS.cpp b/src/hotspot/share/gc/shared/cardTableRS.cpp index 164ad47fe51..3dc15fb23a1 100644 --- a/src/hotspot/share/gc/shared/cardTableRS.cpp +++ b/src/hotspot/share/gc/shared/cardTableRS.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,53 +38,8 @@ #include "runtime/os.hpp" #include "utilities/macros.hpp" -CardTable::CardValue CardTableRS::find_unused_youngergenP_card_value() { - for (CardValue v = youngergenP1_card; - v < cur_youngergen_and_prev_nonclean_card; - v++) { - bool seen = false; - for (int g = 0; g < _regions_to_iterate; g++) { - if (_last_cur_val_in_gen[g] == v) { - seen = true; - break; - } - } - if (!seen) { - return v; - } - } - ShouldNotReachHere(); - return 0; -} - -void CardTableRS::prepare_for_younger_refs_iterate(bool parallel) { - // Parallel or sequential, we must always set the prev to equal the - // last one written. - if (parallel) { - // Find a parallel value to be used next. - jbyte next_val = find_unused_youngergenP_card_value(); - set_cur_youngergen_card_val(next_val); - - } else { - // In an sequential traversal we will always write youngergen, so that - // the inline barrier is correct. - set_cur_youngergen_card_val(youngergen_card); - } -} - -void CardTableRS::at_younger_refs_iterate() { - // The indexing in this array is slightly odd. We want to access - // the old generation record here, which is at index 2. - _last_cur_val_in_gen[2] = cur_youngergen_card_val(); -} - inline bool ClearNoncleanCardWrapper::clear_card(CardValue* entry) { - CardValue entry_val = *entry; - assert(entry_val != CardTableRS::clean_card_val(), - "We shouldn't be looking at clean cards, and this should " - "be the only place they get cleaned."); - assert(entry_val != CardTableRS::cur_youngergen_and_prev_nonclean_card, - "This should be possible in the sequential case."); + assert(*entry == CardTableRS::dirty_card_val(), "Only look at dirty cards."); *entry = CardTableRS::clean_card_val(); return true; } @@ -479,59 +434,11 @@ void CardTableRS::verify() { CardTable::verify(); } -CardTableRS::CardTableRS(MemRegion whole_heap, bool scanned_concurrently) : - CardTable(whole_heap, scanned_concurrently), - _cur_youngergen_card_val(youngergenP1_card), - // LNC functionality - _lowest_non_clean(NULL), - _lowest_non_clean_chunk_size(NULL), - _lowest_non_clean_base_chunk_index(NULL), - _last_LNC_resizing_collection(NULL) -{ - // max_gens is really GenCollectedHeap::heap()->gen_policy()->number_of_generations() - // (which is always 2, young & old), but GenCollectedHeap has not been initialized yet. - uint max_gens = 2; - _last_cur_val_in_gen = NEW_C_HEAP_ARRAY(CardValue, max_gens + 1, mtGC); - for (uint i = 0; i < max_gens + 1; i++) { - _last_cur_val_in_gen[i] = clean_card_val(); - } -} - -CardTableRS::~CardTableRS() { - FREE_C_HEAP_ARRAY(CardValue, _last_cur_val_in_gen); - FREE_C_HEAP_ARRAY(CardArr, _lowest_non_clean); - FREE_C_HEAP_ARRAY(size_t, _lowest_non_clean_chunk_size); - FREE_C_HEAP_ARRAY(uintptr_t, _lowest_non_clean_base_chunk_index); - FREE_C_HEAP_ARRAY(int, _last_LNC_resizing_collection); -} +CardTableRS::CardTableRS(MemRegion whole_heap) : + CardTable(whole_heap) { } void CardTableRS::initialize() { CardTable::initialize(); - _lowest_non_clean = - NEW_C_HEAP_ARRAY(CardArr, _max_covered_regions, mtGC); - _lowest_non_clean_chunk_size = - NEW_C_HEAP_ARRAY(size_t, _max_covered_regions, mtGC); - _lowest_non_clean_base_chunk_index = - NEW_C_HEAP_ARRAY(uintptr_t, _max_covered_regions, mtGC); - _last_LNC_resizing_collection = - NEW_C_HEAP_ARRAY(int, _max_covered_regions, mtGC); - - for (int i = 0; i < _max_covered_regions; i++) { - _lowest_non_clean[i] = NULL; - _lowest_non_clean_chunk_size[i] = 0; - _last_LNC_resizing_collection[i] = -1; - } -} - -bool CardTableRS::card_will_be_scanned(CardValue cv) { - return card_is_dirty_wrt_gen_iter(cv) || is_prev_nonclean_card_val(cv); -} - -bool CardTableRS::card_may_have_been_dirty(CardValue cv) { - return - cv != clean_card && - (card_is_dirty_wrt_gen_iter(cv) || - CardTableRS::youngergen_may_have_been_dirty(cv)); } void CardTableRS::non_clean_card_iterate(Space* sp, diff --git a/src/hotspot/share/gc/shared/cardTableRS.hpp b/src/hotspot/share/gc/shared/cardTableRS.hpp index b7aa07188bd..86ea16e0957 100644 --- a/src/hotspot/share/gc/shared/cardTableRS.hpp +++ b/src/hotspot/share/gc/shared/cardTableRS.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,7 @@ class Space; // This RemSet uses a card table both as shared data structure // for a mod ref barrier set and for the rem set information. -class CardTableRS: public CardTable { +class CardTableRS : public CardTable { friend class VMStructs; // Below are private classes used in impl. friend class VerifyCTSpaceClosure; @@ -44,66 +44,16 @@ class CardTableRS: public CardTable { void verify_space(Space* s, HeapWord* gen_start); - enum ExtendedCardValue { - youngergen_card = CT_MR_BS_last_reserved + 1, - // These are for parallel collection. - // There are three P (parallel) youngergen card values. In general, this - // needs to be more than the number of generations (including the perm - // gen) that might have younger_refs_do invoked on them separately. So - // if we add more gens, we have to add more values. - youngergenP1_card = CT_MR_BS_last_reserved + 2, - youngergenP2_card = CT_MR_BS_last_reserved + 3, - youngergenP3_card = CT_MR_BS_last_reserved + 4, - cur_youngergen_and_prev_nonclean_card = - CT_MR_BS_last_reserved + 5 - }; - - // An array that contains, for each generation, the card table value last - // used as the current value for a younger_refs_do iteration of that - // portion of the table. The perm gen is index 0. The young gen is index 1, - // but will always have the value "clean_card". The old gen is index 2. - CardValue* _last_cur_val_in_gen; - - CardValue _cur_youngergen_card_val; - - // Number of generations, plus one for lingering PermGen issues in CardTableRS. - static const int _regions_to_iterate = 3; - - CardValue cur_youngergen_card_val() { - return _cur_youngergen_card_val; - } - void set_cur_youngergen_card_val(CardValue v) { - _cur_youngergen_card_val = v; - } - bool is_prev_youngergen_card_val(CardValue v) { - return - youngergen_card <= v && - v < cur_youngergen_and_prev_nonclean_card && - v != _cur_youngergen_card_val; - } - // Return a youngergen_card_value that is not currently in use. - CardValue find_unused_youngergenP_card_value(); - public: - CardTableRS(MemRegion whole_heap, bool scanned_concurrently); - ~CardTableRS(); + CardTableRS(MemRegion whole_heap); void younger_refs_in_space_iterate(Space* sp, HeapWord* gen_boundary, OopIterateClosure* cl); virtual void verify_used_region_at_save_marks(Space* sp) const NOT_DEBUG_RETURN; - // Override. - void prepare_for_younger_refs_iterate(bool parallel); - - // Card table entries are cleared before application; - void at_younger_refs_iterate(); - - void inline_write_ref_field_gc(void* field, oop new_val) { + void inline_write_ref_field_gc(void* field) { CardValue* byte = byte_for(field); - *byte = youngergen_card; - } - void write_ref_field_gc_work(void* field, oop new_val) { - inline_write_ref_field_gc(field, new_val); + *byte = dirty_card_val(); } bool is_aligned(HeapWord* addr) { @@ -117,33 +67,6 @@ class CardTableRS: public CardTable { void invalidate_or_clear(Generation* old_gen); - bool is_prev_nonclean_card_val(CardValue v) { - return - youngergen_card <= v && - v <= cur_youngergen_and_prev_nonclean_card && - v != _cur_youngergen_card_val; - } - - static bool youngergen_may_have_been_dirty(CardValue cv) { - return cv == CardTableRS::cur_youngergen_and_prev_nonclean_card; - } - - // *** Support for parallel card scanning. - - // dirty and precleaned are equivalent wrt younger_refs_iter. - static bool card_is_dirty_wrt_gen_iter(CardValue cv) { - return cv == dirty_card; - } - - // Returns "true" iff the value "cv" will cause the card containing it - // to be scanned in the current traversal. May be overridden by - // subtypes. - bool card_will_be_scanned(CardValue cv); - - // Returns "true" iff the value "cv" may have represented a dirty card at - // some point. - bool card_may_have_been_dirty(CardValue cv); - // Iterate over the portion of the card-table which covers the given // region mr in the given space and apply cl to any dirty sub-regions // of mr. Clears the dirty cards as they are processed. @@ -153,18 +76,6 @@ class CardTableRS: public CardTable { OopIterateClosure* cl, CardTableRS* ct); - // This is an array, one element per covered region of the card table. - // Each entry is itself an array, with one element per chunk in the - // covered region. Each entry of these arrays is the lowest non-clean - // card of the corresponding chunk containing part of an object from the - // previous chunk, or else NULL. - typedef CardValue* CardPtr; - typedef CardPtr* CardArr; - CardArr* _lowest_non_clean; - size_t* _lowest_non_clean_chunk_size; - uintptr_t* _lowest_non_clean_base_chunk_index; - volatile int* _last_LNC_resizing_collection; - virtual bool is_in_young(oop obj) const; }; @@ -179,9 +90,6 @@ class ClearNoncleanCardWrapper: public MemRegionClosure { // Clears the given card, return true if the corresponding card should be // processed. inline bool clear_card(CardValue* entry); - // Work methods called by the clear_card() - inline bool clear_card_serial(CardValue* entry); - inline bool clear_card_parallel(CardValue* entry); // check alignment of pointer bool is_word_aligned(CardValue* entry); diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index 105d64ba2f1..c62304e2217 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/classLoaderData.hpp" #include "classfile/vmClasses.hpp" #include "gc/shared/allocTracer.hpp" #include "gc/shared/barrierSet.hpp" diff --git a/src/hotspot/share/gc/shared/collectedHeap.hpp b/src/hotspot/share/gc/shared/collectedHeap.hpp index 66b029d8764..52e675b18a0 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.hpp +++ b/src/hotspot/share/gc/shared/collectedHeap.hpp @@ -29,7 +29,6 @@ #include "gc/shared/gcWhen.hpp" #include "gc/shared/verifyOption.hpp" #include "memory/allocation.hpp" -#include "memory/heapInspection.hpp" #include "memory/universe.hpp" #include "runtime/handles.hpp" #include "runtime/perfDataTypes.hpp" diff --git a/src/hotspot/share/gc/shared/concurrentGCThread.cpp b/src/hotspot/share/gc/shared/concurrentGCThread.cpp index c669bae9860..cd14039a8f1 100644 --- a/src/hotspot/share/gc/shared/concurrentGCThread.cpp +++ b/src/hotspot/share/gc/shared/concurrentGCThread.cpp @@ -26,6 +26,7 @@ #include "gc/shared/concurrentGCThread.hpp" #include "runtime/atomic.hpp" #include "runtime/init.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" diff --git a/src/hotspot/share/gc/shared/concurrentGCThread.hpp b/src/hotspot/share/gc/shared/concurrentGCThread.hpp index 021fdd76498..34c4717c9f3 100644 --- a/src/hotspot/share/gc/shared/concurrentGCThread.hpp +++ b/src/hotspot/share/gc/shared/concurrentGCThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #ifndef SHARE_GC_SHARED_CONCURRENTGCTHREAD_HPP #define SHARE_GC_SHARED_CONCURRENTGCTHREAD_HPP +#include "runtime/nonJavaThread.hpp" #include "runtime/thread.hpp" class ConcurrentGCThread: public NamedThread { diff --git a/src/hotspot/share/gc/shared/gcId.cpp b/src/hotspot/share/gc/shared/gcId.cpp index f48812c6770..acc25f84c37 100644 --- a/src/hotspot/share/gc/shared/gcId.cpp +++ b/src/hotspot/share/gc/shared/gcId.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "jvm.h" #include "gc/shared/gcId.hpp" +#include "runtime/nonJavaThread.hpp" #include "runtime/safepoint.hpp" #include "runtime/thread.inline.hpp" diff --git a/src/hotspot/share/gc/shared/gcVMOperations.cpp b/src/hotspot/share/gc/shared/gcVMOperations.cpp index cee546b267b..f73974981c9 100644 --- a/src/hotspot/share/gc/shared/gcVMOperations.cpp +++ b/src/hotspot/share/gc/shared/gcVMOperations.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "classfile/classLoader.hpp" +#include "classfile/classLoaderData.hpp" #include "classfile/javaClasses.hpp" #include "gc/shared/allocTracer.hpp" #include "gc/shared/gcId.hpp" @@ -34,6 +34,7 @@ #include "interpreter/oopMapCache.hpp" #include "logging/log.hpp" #include "memory/classLoaderMetaspace.hpp" +#include "memory/heapInspection.hpp" #include "memory/oopFactory.hpp" #include "memory/universe.hpp" #include "runtime/handles.inline.hpp" diff --git a/src/hotspot/share/gc/shared/gcVMOperations.hpp b/src/hotspot/share/gc/shared/gcVMOperations.hpp index 8b16d3336a2..aa8e0e93146 100644 --- a/src/hotspot/share/gc/shared/gcVMOperations.hpp +++ b/src/hotspot/share/gc/shared/gcVMOperations.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,11 +27,9 @@ #include "gc/shared/collectedHeap.hpp" #include "gc/shared/genCollectedHeap.hpp" -#include "memory/heapInspection.hpp" #include "memory/metaspace.hpp" #include "prims/jvmtiExport.hpp" #include "runtime/handles.hpp" -#include "runtime/jniHandles.hpp" #include "runtime/synchronizer.hpp" #include "runtime/vmOperations.hpp" diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index 402409161a8..d557c2218e5 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -344,6 +344,7 @@ develop(uintx, MaxVirtMemFraction, 2, \ "Maximum fraction (1/n) of virtual memory used for ergonomically "\ "determining maximum heap size") \ + range(1, max_uintx) \ \ product(bool, UseAdaptiveSizePolicy, true, \ "Use adaptive generation sizing policies") \ diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp index fb303850c08..a0b6d44637c 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp @@ -142,7 +142,7 @@ jint GenCollectedHeap::initialize() { } CardTableRS* GenCollectedHeap::create_rem_set(const MemRegion& reserved_region) { - return new CardTableRS(reserved_region, false /* scan_concurrently */); + return new CardTableRS(reserved_region); } void GenCollectedHeap::initialize_size_policy(size_t init_eden_size, @@ -172,11 +172,12 @@ ReservedHeapSpace GenCollectedHeap::allocate(size_t alignment) { SIZE_FORMAT, total_reserved, alignment); ReservedHeapSpace heap_rs = Universe::reserve_heap(total_reserved, alignment); + size_t used_page_size = ReservedSpace::actual_reserved_page_size(heap_rs); os::trace_page_sizes("Heap", MinHeapSize, total_reserved, - alignment, + used_page_size, heap_rs.base(), heap_rs.size()); diff --git a/src/hotspot/share/gc/shared/genOopClosures.inline.hpp b/src/hotspot/share/gc/shared/genOopClosures.inline.hpp index 231ffe37770..0b547e6dcff 100644 --- a/src/hotspot/share/gc/shared/genOopClosures.inline.hpp +++ b/src/hotspot/share/gc/shared/genOopClosures.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #ifndef SHARE_GC_SHARED_GENOOPCLOSURES_INLINE_HPP #define SHARE_GC_SHARED_GENOOPCLOSURES_INLINE_HPP +#include "classfile/classLoaderData.hpp" #include "gc/shared/cardTableRS.hpp" #include "gc/shared/genCollectedHeap.hpp" #include "gc/shared/genOopClosures.hpp" @@ -82,7 +83,7 @@ void DefNewYoungerGenClosure::barrier(T* p) { oop obj = CompressedOops::decode_not_null(heap_oop); // If p points to a younger generation, mark the card. if (cast_from_oop(obj) < _old_gen_start) { - _rs->inline_write_ref_field_gc(p, obj); + _rs->inline_write_ref_field_gc(p); } } diff --git a/src/hotspot/share/gc/shared/memAllocator.hpp b/src/hotspot/share/gc/shared/memAllocator.hpp index 26e67c19c28..23e27c54c61 100644 --- a/src/hotspot/share/gc/shared/memAllocator.hpp +++ b/src/hotspot/share/gc/shared/memAllocator.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,11 @@ #ifndef SHARE_GC_SHARED_MEMALLOCATOR_HPP #define SHARE_GC_SHARED_MEMALLOCATOR_HPP -#include "gc/shared/collectedHeap.hpp" #include "memory/memRegion.hpp" #include "oops/oopsHierarchy.hpp" +#include "runtime/thread.hpp" #include "utilities/exceptions.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" // These fascilities are used for allocating, and initializing newly allocated objects. diff --git a/src/hotspot/share/gc/shared/referenceProcessor.cpp b/src/hotspot/share/gc/shared/referenceProcessor.cpp index 42bc3500b86..1779bdfabca 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.cpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.cpp @@ -39,6 +39,7 @@ #include "oops/access.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/java.hpp" +#include "runtime/nonJavaThread.hpp" ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL; ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy = NULL; @@ -244,11 +245,6 @@ ReferenceProcessorStats ReferenceProcessor::process_discovered_references( process_phantom_refs(is_alive, keep_alive, complete_gc, task_executor, phase_times); } - if (task_executor != NULL) { - // Record the work done by the parallel workers. - task_executor->set_single_threaded_mode(); - } - phase_times->set_total_time_ms((os::elapsedTime() - start_time) * 1000); return stats; diff --git a/src/hotspot/share/gc/shared/referenceProcessor.hpp b/src/hotspot/share/gc/shared/referenceProcessor.hpp index 695bdf49053..26060e61bc5 100644 --- a/src/hotspot/share/gc/shared/referenceProcessor.hpp +++ b/src/hotspot/share/gc/shared/referenceProcessor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -601,28 +601,6 @@ class ReferenceProcessorAtomicMutator: StackObj { } }; - -// A utility class to temporarily change the MT processing -// disposition of the given ReferenceProcessor instance -// in the scope that contains it. -class ReferenceProcessorMTProcMutator: StackObj { - private: - ReferenceProcessor* _rp; - bool _saved_mt; - - public: - ReferenceProcessorMTProcMutator(ReferenceProcessor* rp, - bool mt): - _rp(rp) { - _saved_mt = _rp->processing_is_mt(); - _rp->set_mt_processing(mt); - } - - ~ReferenceProcessorMTProcMutator() { - _rp->set_mt_processing(_saved_mt); - } -}; - // This class is an interface used to implement task execution for the // reference processing. class AbstractRefProcTaskExecutor { @@ -633,9 +611,6 @@ class AbstractRefProcTaskExecutor { // Executes a task using worker threads. virtual void execute(ProcessTask& task, uint ergo_workers) = 0; - - // Switch to single threaded mode. - virtual void set_single_threaded_mode() { }; }; // Abstract reference processing task to execute. diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp index b1b6a7a1519..63760bc563f 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupTable.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "classfile/altHashing.hpp" #include "classfile/javaClasses.inline.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/gc_globals.hpp" #include "gc/shared/stringdedup/stringDedup.hpp" #include "gc/shared/stringdedup/stringDedupTable.hpp" diff --git a/src/hotspot/share/gc/shared/vmStructs_gc.hpp b/src/hotspot/share/gc/shared/vmStructs_gc.hpp index 85741a05f61..3fda88c4b4e 100644 --- a/src/hotspot/share/gc/shared/vmStructs_gc.hpp +++ b/src/hotspot/share/gc/shared/vmStructs_gc.hpp @@ -279,8 +279,6 @@ declare_constant(CardTable::card_size) \ declare_constant(CardTable::card_size_in_words) \ \ - declare_constant(CardTableRS::youngergen_card) \ - \ declare_constant(CollectedHeap::Serial) \ declare_constant(CollectedHeap::Parallel) \ declare_constant(CollectedHeap::G1) \ diff --git a/src/hotspot/share/gc/shared/workgroup.cpp b/src/hotspot/share/gc/shared/workgroup.cpp index 3a1d7cfd694..f03a0610292 100644 --- a/src/hotspot/share/gc/shared/workgroup.cpp +++ b/src/hotspot/share/gc/shared/workgroup.cpp @@ -352,26 +352,19 @@ void WorkGangBarrierSync::abort() { // SubTasksDone functions. SubTasksDone::SubTasksDone(uint n) : - _tasks(NULL), _n_tasks(n), _threads_completed(0) { + _tasks(NULL), _n_tasks(n) { _tasks = NEW_C_HEAP_ARRAY(bool, n, mtInternal); - clear(); -} - -bool SubTasksDone::valid() { - return _tasks != NULL; -} - -void SubTasksDone::clear() { for (uint i = 0; i < _n_tasks; i++) { _tasks[i] = false; } - _threads_completed = 0; } -void SubTasksDone::all_tasks_completed_impl(uint n_threads, - uint skipped[], - size_t skipped_size) { #ifdef ASSERT +void SubTasksDone::all_tasks_claimed_impl(uint skipped[], size_t skipped_size) { + if (Atomic::cmpxchg(&_verification_done, false, true)) { + // another thread has done the verification + return; + } // all non-skipped tasks are claimed for (uint i = 0; i < _n_tasks; ++i) { if (!_tasks[i]) { @@ -391,19 +384,8 @@ void SubTasksDone::all_tasks_completed_impl(uint n_threads, assert(task_index < _n_tasks, "Array in range."); assert(!_tasks[task_index], "%d is both claimed and skipped.", task_index); } -#endif - uint observed = _threads_completed; - uint old; - do { - old = observed; - observed = Atomic::cmpxchg(&_threads_completed, old, old+1); - } while (observed != old); - // If this was the last thread checking in, clear the tasks. - uint adjusted_thread_count = (n_threads == 0 ? 1 : n_threads); - if (observed + 1 == adjusted_thread_count) { - clear(); - } } +#endif bool SubTasksDone::try_claim_task(uint t) { assert(t < _n_tasks, "bad task id."); @@ -411,6 +393,7 @@ bool SubTasksDone::try_claim_task(uint t) { } SubTasksDone::~SubTasksDone() { + assert(_verification_done, "all_tasks_claimed must have been called."); FREE_C_HEAP_ARRAY(bool, _tasks); } diff --git a/src/hotspot/share/gc/shared/workgroup.hpp b/src/hotspot/share/gc/shared/workgroup.hpp index 542e86226dc..e6c7a686765 100644 --- a/src/hotspot/share/gc/shared/workgroup.hpp +++ b/src/hotspot/share/gc/shared/workgroup.hpp @@ -29,6 +29,7 @@ #include "metaprogramming/enableIf.hpp" #include "metaprogramming/logical.hpp" #include "runtime/globals.hpp" +#include "runtime/nonJavaThread.hpp" #include "runtime/thread.hpp" #include "gc/shared/gcId.hpp" #include "logging/log.hpp" @@ -304,24 +305,18 @@ class WorkGangBarrierSync : public StackObj { class SubTasksDone: public CHeapObj { volatile bool* _tasks; uint _n_tasks; - volatile uint _threads_completed; - // Set all tasks to unclaimed. - void clear(); - - void all_tasks_completed_impl(uint n_threads, uint skipped[], size_t skipped_size); + // make sure verification logic is run exactly once to avoid duplicate assertion failures + DEBUG_ONLY(volatile bool _verification_done = false;) + void all_tasks_claimed_impl(uint skipped[], size_t skipped_size) NOT_DEBUG_RETURN; NONCOPYABLE(SubTasksDone); public: // Initializes "this" to a state in which there are "n" tasks to be - // processed, none of the which are originally claimed. The number of - // threads doing the tasks is initialized 1. + // processed, none of the which are originally claimed. SubTasksDone(uint n); - // True iff the object is in a valid state. - bool valid(); - // Attempt to claim the task "t", returning true if successful, // false if it has already been claimed. The task "t" is required // to be within the range of "this". @@ -330,21 +325,17 @@ class SubTasksDone: public CHeapObj { // The calling thread asserts that it has attempted to claim all the tasks // that it will try to claim. Tasks that are meant to be skipped must be // explicitly passed as extra arguments. Every thread in the parallel task - // must execute this. (When the last thread does so, the task array is - // cleared.) - // - // n_threads - Number of threads executing the sub-tasks. - void all_tasks_completed(uint n_threads) { - all_tasks_completed_impl(n_threads, nullptr, 0); - } - - // Augmented by variadic args, each for a skipped task. + // must execute this. template...>::value)> - void all_tasks_completed(uint n_threads, T0 first_skipped, Ts... more_skipped) { + void all_tasks_claimed(T0 first_skipped, Ts... more_skipped) { static_assert(std::is_convertible::value, "not convertible"); uint skipped[] = { static_cast(first_skipped), static_cast(more_skipped)... }; - all_tasks_completed_impl(n_threads, skipped, ARRAY_SIZE(skipped)); + all_tasks_claimed_impl(skipped, ARRAY_SIZE(skipped)); + } + // if there are no skipped tasks. + void all_tasks_claimed() { + all_tasks_claimed_impl(nullptr, 0); } // Destructor. diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index ee04b1741c8..9d12a273e5e 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -2282,7 +2282,7 @@ void MemoryGraphFixer::collect_memory_nodes() { uint last = _phase->C->unique(); #ifdef ASSERT - uint8_t max_depth = 0; + uint16_t max_depth = 0; for (LoopTreeIterator iter(_phase->ltree_root()); !iter.done(); iter.next()) { IdealLoopTree* lpt = iter.current(); max_depth = MAX2(max_depth, lpt->_nest); diff --git a/src/hotspot/share/gc/shenandoah/mode/shenandoahIUMode.cpp b/src/hotspot/share/gc/shenandoah/mode/shenandoahIUMode.cpp index abc4a7cfdc9..00e71f4afc4 100644 --- a/src/hotspot/share/gc/shenandoah/mode/shenandoahIUMode.cpp +++ b/src/hotspot/share/gc/shenandoah/mode/shenandoahIUMode.cpp @@ -34,6 +34,11 @@ #include "runtime/java.hpp" void ShenandoahIUMode::initialize_flags() const { + if (FLAG_IS_CMDLINE(ClassUnloadingWithConcurrentMark) && ClassUnloading) { + log_warning(gc)("Shenandoah I-U mode sets -XX:-ClassUnloadingWithConcurrentMark; see JDK-8261341 for details"); + } + FLAG_SET_DEFAULT(ClassUnloadingWithConcurrentMark, false); + if (ClassUnloading) { FLAG_SET_DEFAULT(ShenandoahSuspendibleWorkers, true); FLAG_SET_DEFAULT(VerifyBeforeExit, false); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index c8f2dd23a60..24bea946506 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -26,7 +26,6 @@ #include "gc/shared/barrierSetNMethod.hpp" #include "gc/shared/collectorCounters.hpp" -#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahConcurrentGC.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" @@ -44,7 +43,6 @@ #include "gc/shenandoah/shenandoahWorkGroup.hpp" #include "gc/shenandoah/shenandoahWorkerPolicy.hpp" #include "prims/jvmtiTagMap.hpp" -#include "runtime/vmThread.hpp" #include "utilities/events.hpp" ShenandoahConcurrentGC::ShenandoahConcurrentGC() : diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp index 4f1c3c31d6b..38c4adfad7d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp @@ -24,15 +24,9 @@ #include "precompiled.hpp" -#include "classfile/symbolTable.hpp" -#include "code/codeCache.hpp" - -#include "gc/shared/weakProcessor.inline.hpp" -#include "gc/shared/gcTimer.hpp" -#include "gc/shared/gcTrace.hpp" #include "gc/shared/satbMarkQueue.hpp" #include "gc/shared/strongRootsScope.hpp" - +#include "gc/shared/taskTerminator.hpp" #include "gc/shenandoah/shenandoahBarrierSet.inline.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" #include "gc/shenandoah/shenandoahConcurrentMark.hpp" @@ -45,13 +39,8 @@ #include "gc/shenandoah/shenandoahStringDedup.hpp" #include "gc/shenandoah/shenandoahTaskqueue.inline.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" - #include "memory/iterator.inline.hpp" -#include "memory/metaspace.hpp" #include "memory/resourceArea.hpp" -#include "oops/oop.inline.hpp" -#include "runtime/handles.inline.hpp" - class ShenandoahUpdateRootsTask : public AbstractGangTask { private: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.hpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.hpp index 5865b55d730..fbcd075117a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.hpp @@ -25,14 +25,10 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCONCURRENTMARK_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHCONCURRENTMARK_HPP -#include "gc/shared/taskqueue.hpp" -#include "gc/shared/taskTerminator.hpp" #include "gc/shenandoah/shenandoahMark.hpp" -#include "gc/shenandoah/shenandoahOopClosures.hpp" -#include "gc/shenandoah/shenandoahTaskqueue.hpp" -class ShenandoahStrDedupQueue; -class ShenandoahReferenceProcessor; +class ShenandoahConcurrentMarkingTask; +class ShenandoahFinalMarkingTask; class ShenandoahConcurrentMark: public ShenandoahMark { friend class ShenandoahConcurrentMarkingTask; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp index 1a3030e1d24..4483488739d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp @@ -100,7 +100,7 @@ void ShenandoahControlThread::run_service() { bool implicit_gc_requested = _gc_requested.is_set() && !is_explicit_gc(_requested_gc_cause); // This control loop iteration have seen this much allocations. - size_t allocs_seen = Atomic::xchg(&_allocs_seen, (size_t)0); + size_t allocs_seen = Atomic::xchg(&_allocs_seen, (size_t)0, memory_order_relaxed); // Check if we have seen a new target for soft max heap size. bool soft_max_changed = check_soft_max_changed(); @@ -595,7 +595,7 @@ void ShenandoahControlThread::notify_heap_changed() { void ShenandoahControlThread::pacing_notify_alloc(size_t words) { assert(ShenandoahPacing, "should only call when pacing is enabled"); - Atomic::add(&_allocs_seen, words); + Atomic::add(&_allocs_seen, words, memory_order_relaxed); } void ShenandoahControlThread::set_forced_counters_update(bool value) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp index c7837221e82..6e209d993d2 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp @@ -25,7 +25,6 @@ #include "precompiled.hpp" #include "gc/shared/collectorCounters.hpp" -#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahConcurrentMark.hpp" #include "gc/shenandoah/shenandoahDegeneratedGC.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp index ffa1dc2348b..e7b87f7dcbf 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp @@ -23,11 +23,11 @@ */ #include "precompiled.hpp" -#include "code/codeCache.hpp" + #include "gc/shared/gcTraceTime.inline.hpp" #include "gc/shared/preservedMarks.inline.hpp" #include "gc/shared/tlab_globals.hpp" -#include "gc/shenandoah/shenandoahForwarding.inline.hpp" +#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "gc/shenandoah/shenandoahConcurrentGC.hpp" #include "gc/shenandoah/shenandoahCollectionSet.hpp" #include "gc/shenandoah/shenandoahFreeSet.hpp" @@ -39,6 +39,7 @@ #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp" +#include "gc/shenandoah/shenandoahMetrics.hpp" #include "gc/shenandoah/shenandoahOopClosures.inline.hpp" #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp" @@ -47,7 +48,6 @@ #include "gc/shenandoah/shenandoahVerifier.hpp" #include "gc/shenandoah/shenandoahVMOperations.hpp" #include "gc/shenandoah/shenandoahWorkerPolicy.hpp" -#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" #include "memory/metaspace.hpp" #include "memory/universe.hpp" #include "oops/compressedOops.inline.hpp" @@ -958,7 +958,7 @@ void ShenandoahFullGC::compact_humongous_objects() { Copy::aligned_conjoint_words(heap->get_region(old_start)->bottom(), heap->get_region(new_start)->bottom(), - ShenandoahHeapRegion::region_size_words()*num_regions); + words_size); oop new_obj = oop(heap->get_region(new_start)->bottom()); new_obj->init_mark(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.hpp b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.hpp index 0fcdc9dd0c8..d829306a599 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.hpp @@ -27,9 +27,7 @@ #include "gc/shared/gcTimer.hpp" #include "gc/shenandoah/shenandoahGC.hpp" -#include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahHeapRegionSet.hpp" -#include "gc/shenandoah/shenandoahMetrics.hpp" /** * This implements Full GC (e.g. when invoking System.gc()) using a mark-compact algorithm. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index 375bbd441b6..2970538452f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -620,12 +620,11 @@ void ShenandoahHeap::post_initialize() { } size_t ShenandoahHeap::used() const { - return Atomic::load_acquire(&_used); + return Atomic::load(&_used); } size_t ShenandoahHeap::committed() const { - OrderAccess::acquire(); - return _committed; + return Atomic::load(&_committed); } void ShenandoahHeap::increase_committed(size_t bytes) { @@ -639,20 +638,20 @@ void ShenandoahHeap::decrease_committed(size_t bytes) { } void ShenandoahHeap::increase_used(size_t bytes) { - Atomic::add(&_used, bytes); + Atomic::add(&_used, bytes, memory_order_relaxed); } void ShenandoahHeap::set_used(size_t bytes) { - Atomic::release_store_fence(&_used, bytes); + Atomic::store(&_used, bytes); } void ShenandoahHeap::decrease_used(size_t bytes) { assert(used() >= bytes, "never decrease heap size by more than we've left"); - Atomic::sub(&_used, bytes); + Atomic::sub(&_used, bytes, memory_order_relaxed); } void ShenandoahHeap::increase_allocated(size_t bytes) { - Atomic::add(&_bytes_allocated_since_gc_start, bytes); + Atomic::add(&_bytes_allocated_since_gc_start, bytes, memory_order_relaxed); } void ShenandoahHeap::notify_mutator_alloc_words(size_t words, bool waste) { @@ -1883,11 +1882,11 @@ address ShenandoahHeap::gc_state_addr() { } size_t ShenandoahHeap::bytes_allocated_since_gc_start() { - return Atomic::load_acquire(&_bytes_allocated_since_gc_start); + return Atomic::load(&_bytes_allocated_since_gc_start); } void ShenandoahHeap::reset_bytes_allocated_since_gc_start() { - Atomic::release_store_fence(&_bytes_allocated_since_gc_start, (size_t)0); + Atomic::store(&_bytes_allocated_since_gc_start, (size_t)0); } void ShenandoahHeap::set_degenerated_gc_in_progress(bool in_progress) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp index c02c00b7d4f..461aa30fcbe 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp @@ -80,7 +80,7 @@ inline void ShenandoahHeapRegion::increase_live_data_gc_words(size_t s) { } inline void ShenandoahHeapRegion::internal_increase_live_data(size_t s) { - size_t new_live_data = Atomic::add(&_live_data, s); + size_t new_live_data = Atomic::add(&_live_data, s, memory_order_relaxed); #ifdef ASSERT size_t live_bytes = new_live_data * HeapWordSize; size_t used_bytes = used(); @@ -90,11 +90,11 @@ inline void ShenandoahHeapRegion::internal_increase_live_data(size_t s) { } inline void ShenandoahHeapRegion::clear_live_data() { - Atomic::release_store_fence(&_live_data, (size_t)0); + Atomic::store(&_live_data, (size_t)0); } inline size_t ShenandoahHeapRegion::get_live_data_words() const { - return Atomic::load_acquire(&_live_data); + return Atomic::load(&_live_data); } inline size_t ShenandoahHeapRegion::get_live_data_bytes() const { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMark.cpp index aa987658158..85499b145bd 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMark.cpp @@ -25,8 +25,6 @@ #include "precompiled.hpp" -#include "gc/shared/gcTrace.hpp" -#include "gc/shared/referenceProcessorPhaseTimes.hpp" #include "gc/shenandoah/shenandoahBarrierSet.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" #include "gc/shenandoah/shenandoahMark.inline.hpp" @@ -35,7 +33,6 @@ #include "gc/shenandoah/shenandoahTaskqueue.inline.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahVerifier.hpp" -#include "memory/iterator.inline.hpp" ShenandoahMarkRefsSuperClosure::ShenandoahMarkRefsSuperClosure(ShenandoahObjToScanQueue* q, ShenandoahReferenceProcessor* rp) : MetadataVisitingOopIterateClosure(rp), diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp index 412fb0395be..9fea8f8d862 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp @@ -27,7 +27,6 @@ #include "gc/shared/taskTerminator.hpp" #include "gc/shenandoah/shenandoahOopClosures.hpp" -#include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "gc/shenandoah/shenandoahTaskqueue.hpp" class ShenandoahCMDrainMarkingStackClosure; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.hpp index a37523f8197..a71cad75bae 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.hpp @@ -82,8 +82,6 @@ class ShenandoahMarkBitMap { return map() + to_words_align_down(bit); } - static inline const bm_word_t load_word_ordered(const volatile bm_word_t* const addr, atomic_memory_order memory_order); - bool at(idx_t index) const { verify_index(index); return (*word_addr(index) & bit_mask(index)) != 0; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp index b9e0bb61f54..9dd3f729899 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkBitMap.inline.hpp @@ -46,7 +46,7 @@ inline bool ShenandoahMarkBitMap::mark_strong(HeapWord* heap_addr, bool& was_upg volatile bm_word_t* const addr = word_addr(bit); const bm_word_t mask = bit_mask(bit); const bm_word_t mask_weak = (bm_word_t)1 << (bit_in_word(bit) + 1); - bm_word_t old_val = load_word_ordered(addr, memory_order_conservative); + bm_word_t old_val = Atomic::load(addr); do { const bm_word_t new_val = old_val | mask; @@ -54,7 +54,7 @@ inline bool ShenandoahMarkBitMap::mark_strong(HeapWord* heap_addr, bool& was_upg assert(!was_upgraded, "Should be false already"); return false; // Someone else beat us to it. } - const bm_word_t cur_val = Atomic::cmpxchg(addr, old_val, new_val, memory_order_conservative); + const bm_word_t cur_val = Atomic::cmpxchg(addr, old_val, new_val, memory_order_relaxed); if (cur_val == old_val) { was_upgraded = (cur_val & mask_weak) != 0; return true; // Success. @@ -71,7 +71,7 @@ inline bool ShenandoahMarkBitMap::mark_weak(HeapWord* heap_addr) { volatile bm_word_t* const addr = word_addr(bit); const bm_word_t mask_weak = (bm_word_t)1 << (bit_in_word(bit) + 1); const bm_word_t mask_strong = (bm_word_t)1 << bit_in_word(bit); - bm_word_t old_val = load_word_ordered(addr, memory_order_conservative); + bm_word_t old_val = Atomic::load(addr); do { if ((old_val & mask_strong) != 0) { @@ -81,7 +81,7 @@ inline bool ShenandoahMarkBitMap::mark_weak(HeapWord* heap_addr) { if (new_val == old_val) { return false; // Someone else beat us to it. } - const bm_word_t cur_val = Atomic::cmpxchg(addr, old_val, new_val, memory_order_conservative); + const bm_word_t cur_val = Atomic::cmpxchg(addr, old_val, new_val, memory_order_relaxed); if (cur_val == old_val) { return true; // Success. } @@ -107,18 +107,6 @@ inline bool ShenandoahMarkBitMap::is_marked(HeapWord* addr) const { return (*word_addr(index) & mask) != 0; } -inline const ShenandoahMarkBitMap::bm_word_t ShenandoahMarkBitMap::load_word_ordered(const volatile bm_word_t* const addr, atomic_memory_order memory_order) { - if (memory_order == memory_order_relaxed || memory_order == memory_order_release) { - return Atomic::load(addr); - } else { - assert(memory_order == memory_order_acq_rel || - memory_order == memory_order_acquire || - memory_order == memory_order_conservative, - "unexpected memory ordering"); - return Atomic::load_acquire(addr); - } -} - template inline ShenandoahMarkBitMap::idx_t ShenandoahMarkBitMap::get_next_bit_impl(idx_t l_index, idx_t r_index) const { STATIC_ASSERT(flip == find_ones_flip || flip == find_zeros_flip); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp b/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp index d8866ebd6dd..745d6d88c87 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp @@ -179,7 +179,7 @@ size_t ShenandoahPacer::update_and_get_progress_history() { void ShenandoahPacer::restart_with(size_t non_taxable_bytes, double tax_rate) { size_t initial = (size_t)(non_taxable_bytes * tax_rate) >> LogHeapWordSize; STATIC_ASSERT(sizeof(size_t) <= sizeof(intptr_t)); - Atomic::xchg(&_budget, (intptr_t)initial); + Atomic::xchg(&_budget, (intptr_t)initial, memory_order_relaxed); Atomic::store(&_tax_rate, tax_rate); Atomic::inc(&_epoch); @@ -201,14 +201,14 @@ bool ShenandoahPacer::claim_for_alloc(size_t words, bool force) { return false; } new_val = cur - tax; - } while (Atomic::cmpxchg(&_budget, cur, new_val) != cur); + } while (Atomic::cmpxchg(&_budget, cur, new_val, memory_order_relaxed) != cur); return true; } void ShenandoahPacer::unpace_for_alloc(intptr_t epoch, size_t words) { assert(ShenandoahPacing, "Only be here when pacing is enabled"); - if (_epoch != epoch) { + if (Atomic::load(&_epoch) != epoch) { // Stale ticket, no need to unpace. return; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPacer.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahPacer.inline.hpp index c416d85234f..783755a4320 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPacer.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPacer.inline.hpp @@ -53,13 +53,13 @@ inline void ShenandoahPacer::report_internal(size_t words) { inline void ShenandoahPacer::report_progress_internal(size_t words) { assert(ShenandoahPacing, "Only be here when pacing is enabled"); STATIC_ASSERT(sizeof(size_t) <= sizeof(intptr_t)); - Atomic::add(&_progress, (intptr_t)words); + Atomic::add(&_progress, (intptr_t)words, memory_order_relaxed); } inline void ShenandoahPacer::add_budget(size_t words) { STATIC_ASSERT(sizeof(size_t) <= sizeof(intptr_t)); intptr_t inc = (intptr_t) words; - intptr_t new_budget = Atomic::add(&_budget, inc); + intptr_t new_budget = Atomic::add(&_budget, inc, memory_order_relaxed); // Was the budget replenished beyond zero? Then all pacing claims // are satisfied, notify the waiters. Avoid taking any locks here, diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp index 9aa10d17d32..91d5a278e1e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp @@ -46,7 +46,7 @@ ShenandoahJavaThreadsIterator::ShenandoahJavaThreadsIterator(ShenandoahPhaseTimi } uint ShenandoahJavaThreadsIterator::claim() { - return Atomic::fetch_and_add(&_claimed, _stride); + return Atomic::fetch_and_add(&_claimed, _stride, memory_order_relaxed); } void ShenandoahJavaThreadsIterator::threads_do(ThreadClosure* cl, uint worker_id) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp index c273b6eea80..6992279c41e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp @@ -36,6 +36,7 @@ #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shared/oopStorage.inline.hpp" #include "gc/shared/oopStorageSet.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/thread.hpp" #include "utilities/debug.hpp" #include "utilities/enumIterator.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp index 6dfe8adb29f..dbdffd1417b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp @@ -26,6 +26,7 @@ #include "precompiled.hpp" #include "gc/shared/strongRootsScope.hpp" +#include "gc/shared/taskTerminator.hpp" #include "gc/shared/workgroup.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" #include "gc/shenandoah/shenandoahMark.inline.hpp" @@ -35,7 +36,6 @@ #include "gc/shenandoah/shenandoahSTWMark.hpp" #include "gc/shenandoah/shenandoahVerifier.hpp" - class ShenandoahSTWMarkTask : public AbstractGangTask { private: ShenandoahSTWMark* const _mark; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.hpp b/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.hpp index d16de30c61e..771e36e0ec1 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.hpp @@ -25,9 +25,7 @@ #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHSTWMARK_HPP #define SHARE_GC_SHENANDOAH_SHENANDOAHSTWMARK_HPP -#include "gc/shared/taskTerminator.hpp" #include "gc/shenandoah/shenandoahMark.hpp" -#include "gc/shenandoah/shenandoahRootProcessor.hpp" class ShenandoahSTWMarkTask; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp index 3eb2bbc78c9..b7ab52e2bbb 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp @@ -160,7 +160,7 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { // skip break; case ShenandoahVerifier::_verify_liveness_complete: - Atomic::add(&_ld[obj_reg->index()], (uint) obj->size()); + Atomic::add(&_ld[obj_reg->index()], (uint) obj->size(), memory_order_relaxed); // fallthrough for fast failure for un-live regions: case ShenandoahVerifier::_verify_liveness_conservative: check(ShenandoahAsserts::_safe_oop, obj, obj_reg->has_live(), @@ -483,7 +483,7 @@ class ShenandoahVerifierReachableTask : public AbstractGangTask { } } - Atomic::add(&_processed, processed); + Atomic::add(&_processed, processed, memory_order_relaxed); } }; @@ -512,7 +512,7 @@ class ShenandoahVerifierMarkedRegionTask : public AbstractGangTask { _processed(0) {}; size_t processed() { - return _processed; + return Atomic::load(&_processed); } virtual void work(uint worker_id) { @@ -522,7 +522,7 @@ class ShenandoahVerifierMarkedRegionTask : public AbstractGangTask { _options); while (true) { - size_t v = Atomic::fetch_and_add(&_claimed, 1u); + size_t v = Atomic::fetch_and_add(&_claimed, 1u, memory_order_relaxed); if (v < _heap->num_regions()) { ShenandoahHeapRegion* r = _heap->get_region(v); if (!r->is_humongous() && !r->is_trash()) { @@ -542,7 +542,7 @@ class ShenandoahVerifierMarkedRegionTask : public AbstractGangTask { if (_heap->complete_marking_context()->is_marked((oop)obj)) { verify_and_follow(obj, stack, cl, &processed); } - Atomic::add(&_processed, processed); + Atomic::add(&_processed, processed, memory_order_relaxed); } virtual void work_regular(ShenandoahHeapRegion *r, ShenandoahVerifierStack &stack, ShenandoahVerifyOopClosure &cl) { @@ -575,7 +575,7 @@ class ShenandoahVerifierMarkedRegionTask : public AbstractGangTask { } } - Atomic::add(&_processed, processed); + Atomic::add(&_processed, processed, memory_order_relaxed); } void verify_and_follow(HeapWord *addr, ShenandoahVerifierStack &stack, ShenandoahVerifyOopClosure &cl, size_t *processed) { @@ -747,12 +747,12 @@ void ShenandoahVerifier::verify_at_safepoint(const char *label, if (r->is_humongous()) { // For humongous objects, test if start region is marked live, and if so, // all humongous regions in that chain have live data equal to their "used". - juint start_live = Atomic::load_acquire(&ld[r->humongous_start_region()->index()]); + juint start_live = Atomic::load(&ld[r->humongous_start_region()->index()]); if (start_live > 0) { verf_live = (juint)(r->used() / HeapWordSize); } } else { - verf_live = Atomic::load_acquire(&ld[r->index()]); + verf_live = Atomic::load(&ld[r->index()]); } size_t reg_live = r->get_live_data_words(); diff --git a/src/hotspot/share/gc/z/zCollectedHeap.cpp b/src/hotspot/share/gc/z/zCollectedHeap.cpp index f07d4b4c7aa..24bd1e31816 100644 --- a/src/hotspot/share/gc/z/zCollectedHeap.cpp +++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,7 @@ */ #include "precompiled.hpp" +#include "classfile/classLoaderData.hpp" #include "gc/shared/gcHeapSummary.hpp" #include "gc/shared/suspendibleThreadSet.hpp" #include "gc/z/zCollectedHeap.hpp" diff --git a/src/hotspot/share/gc/z/zThread.cpp b/src/hotspot/share/gc/z/zThread.cpp index 37fb595a343..7dc539f4b35 100644 --- a/src/hotspot/share/gc/z/zThread.cpp +++ b/src/hotspot/share/gc/z/zThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ #include "precompiled.hpp" #include "gc/z/zThread.inline.hpp" +#include "runtime/nonJavaThread.hpp" #include "runtime/thread.hpp" #include "utilities/debug.hpp" diff --git a/src/hotspot/share/interpreter/interpreterRuntime.hpp b/src/hotspot/share/interpreter/interpreterRuntime.hpp index 92ff26b19c0..249a2d47f71 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.hpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.hpp @@ -33,6 +33,7 @@ #include "runtime/thread.hpp" #include "utilities/macros.hpp" +class BufferBlob; class CodeBuffer; // The InterpreterRuntime is called by the interpreter for everything diff --git a/src/hotspot/share/interpreter/oopMapCache.cpp b/src/hotspot/share/interpreter/oopMapCache.cpp index 152d59d643f..55d8ff714e6 100644 --- a/src/hotspot/share/interpreter/oopMapCache.cpp +++ b/src/hotspot/share/interpreter/oopMapCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/safepoint.hpp" #include "runtime/signature.hpp" class OopMapCacheEntry: private InterpreterOopMap { diff --git a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp index 98ee0800cf6..becff878805 100644 --- a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp +++ b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp @@ -34,6 +34,7 @@ #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/jniHandles.hpp" #include "services/diagnosticArgument.hpp" #include "services/diagnosticFramework.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp index d8c9acc8e8e..3bf90ccacbf 100644 --- a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp +++ b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp @@ -52,6 +52,7 @@ #include "oops/method.hpp" #include "prims/jvmtiRedefineClasses.hpp" #include "runtime/handles.inline.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/os.hpp" #include "runtime/thread.inline.hpp" #include "utilities/exceptions.hpp" diff --git a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp index 3ec449a6b95..6564cff136f 100644 --- a/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp +++ b/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp @@ -38,6 +38,7 @@ #include "oops/oop.hpp" #include "prims/jvmtiThreadState.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/vframe_hp.hpp" #include "services/management.hpp" diff --git a/src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.cpp b/src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.cpp index c5ba05ce3d5..ff6d87c97ba 100644 --- a/src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.cpp +++ b/src/hotspot/share/jfr/leakprofiler/sampling/objectSampler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/oopStorage.hpp" #include "gc/shared/oopStorageSet.hpp" #include "jfr/jfrEvents.hpp" diff --git a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp index 45a3db36338..55c1b7ece4c 100644 --- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp +++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp @@ -369,9 +369,10 @@ static void write_emergency_dump_file(const RepositoryIterator& iterator) { if (copy_block == NULL) { log_error(jfr, system)("Unable to malloc memory during jfr emergency dump"); log_error(jfr, system)("Unable to write jfr emergency dump file"); + } else { + write_repository_files(iterator, copy_block, block_size); + os::free(copy_block); } - write_repository_files(iterator, copy_block, block_size); - os::free(copy_block); } void JfrEmergencyDump::on_vm_error(const char* repository_path) { diff --git a/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp b/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp index 1b11b6e6db3..04e35440e40 100644 --- a/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp +++ b/src/hotspot/share/jfr/recorder/storage/jfrVirtualMemory.cpp @@ -213,6 +213,7 @@ class JfrVirtualMemoryManager : public JfrCHeapObj { return reserved_high() == committed_high(); } + u1* top() const { return reinterpret_cast(_current_segment->top()); } const u1* committed_low() const { return _current_segment->committed_low(); } const u1* committed_high() const { return _current_segment->committed_high(); } const u1* reserved_low() const { return _current_segment->reserved_low(); } @@ -443,11 +444,10 @@ void* JfrVirtualMemory::initialize(size_t reservation_size_request_bytes, } _reserved_low = (const u1*)_vmm->reserved_low(); _reserved_high = (const u1*)_vmm->reserved_high(); + assert(static_cast(_reserved_high - _reserved_low) == reservation_size_request_bytes, "invariant"); // reservation complete - _top = (u1*)_vmm->committed_high(); - _commit_point = _top; + _top = _vmm->top(); assert(_reserved_low == _top, "invariant"); // initial empty state - assert((size_t)(_reserved_high - _reserved_low) == reservation_size_request_bytes, "invariant"); // initial commit commit_memory_block(); return _top; @@ -470,8 +470,6 @@ bool JfrVirtualMemory::is_empty() const { bool JfrVirtualMemory::commit_memory_block() { assert(_vmm != NULL, "invariant"); assert(!is_full(), "invariant"); - assert(_top == _commit_point, "invariant"); - void* const block = _vmm->commit(_physical_commit_size_request_words); if (block != NULL) { _commit_point = _vmm->committed_high(); diff --git a/src/hotspot/share/jfr/utilities/jfrThreadIterator.hpp b/src/hotspot/share/jfr/utilities/jfrThreadIterator.hpp index 59fa255d759..f45ed6bf4e3 100644 --- a/src/hotspot/share/jfr/utilities/jfrThreadIterator.hpp +++ b/src/hotspot/share/jfr/utilities/jfrThreadIterator.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ #define SHARE_VM_JFR_UTILITIES_JFRTHREADITERATOR_HPP #include "memory/allocation.hpp" +#include "runtime/nonJavaThread.hpp" #include "runtime/thread.hpp" #include "runtime/threadSMR.hpp" diff --git a/src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp b/src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp index 1f71b842946..57dc4122807 100644 --- a/src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp +++ b/src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp @@ -34,6 +34,7 @@ #include "oops/oop.hpp" #include "oops/symbol.hpp" #include "oops/typeArrayOop.inline.hpp" +#include "runtime/jniHandles.hpp" inline bool compressed_integers() { static const bool comp_integers = JfrOptionSet::compressed_integers(); diff --git a/src/hotspot/share/jvmci/jvmci.cpp b/src/hotspot/share/jvmci/jvmci.cpp index 7ab4ae20e08..6c8a4ed16ed 100644 --- a/src/hotspot/share/jvmci/jvmci.cpp +++ b/src/hotspot/share/jvmci/jvmci.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" #include "compiler/compileTask.hpp" +#include "compiler/compilerThread.hpp" #include "gc/shared/collectedHeap.hpp" #include "jvmci/jvmci.hpp" #include "jvmci/jvmciJavaClasses.hpp" diff --git a/src/hotspot/share/jvmci/jvmciEnv.hpp b/src/hotspot/share/jvmci/jvmciEnv.hpp index 3f5658a19ad..9a509f5f94a 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.hpp +++ b/src/hotspot/share/jvmci/jvmciEnv.hpp @@ -27,6 +27,7 @@ #include "classfile/javaClasses.hpp" #include "jvmci/jvmciJavaClasses.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/thread.hpp" class CompileTask; diff --git a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp index 25d0a109e7e..4db609d18d1 100644 --- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp @@ -27,7 +27,6 @@ #include "classfile/vmSymbols.hpp" #include "jvmci/jvmciExceptions.hpp" #include "jvmci/jvmciObject.hpp" -#include "runtime/jniHandles.hpp" /* * This macro defines the structure of the JVMCI classes accessed from VM code. It is used to diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 2d0c5b6881b..c4278a9f231 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -27,6 +27,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmClasses.hpp" #include "compiler/compileBroker.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/oopStorage.inline.hpp" #include "jvmci/jniAccessMark.inline.hpp" #include "jvmci/jvmciCompilerToVM.hpp" diff --git a/src/hotspot/share/jvmci/jvmci_globals.cpp b/src/hotspot/share/jvmci/jvmci_globals.cpp index 4cfab9e9c60..cf213e54692 100644 --- a/src/hotspot/share/jvmci/jvmci_globals.cpp +++ b/src/hotspot/share/jvmci/jvmci_globals.cpp @@ -27,6 +27,7 @@ #include "gc/shared/gcConfig.hpp" #include "jvm.h" #include "jvmci/jvmci_globals.hpp" +#include "logging/log.hpp" #include "runtime/arguments.hpp" #include "runtime/flags/jvmFlagAccess.hpp" #include "runtime/globals_extension.hpp" diff --git a/src/hotspot/share/jvmci/metadataHandles.cpp b/src/hotspot/share/jvmci/metadataHandles.cpp index da1ad7b61a0..bcf66721f52 100644 --- a/src/hotspot/share/jvmci/metadataHandles.cpp +++ b/src/hotspot/share/jvmci/metadataHandles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,7 @@ */ #include "precompiled.hpp" +#include "classfile/classLoaderData.hpp" #include "jvmci/metadataHandles.hpp" #include "runtime/atomic.hpp" diff --git a/src/hotspot/share/memory/allocation.cpp b/src/hotspot/share/memory/allocation.cpp index a4c55edac87..c3024bcb372 100644 --- a/src/hotspot/share/memory/allocation.cpp +++ b/src/hotspot/share/memory/allocation.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "memory/arena.hpp" -#include "memory/metaspaceShared.hpp" +#include "memory/metaspace.hpp" #include "memory/resourceArea.hpp" #include "runtime/os.hpp" #include "runtime/task.hpp" diff --git a/src/hotspot/share/memory/archiveBuilder.cpp b/src/hotspot/share/memory/archiveBuilder.cpp index 21da4eff168..5855311db34 100644 --- a/src/hotspot/share/memory/archiveBuilder.cpp +++ b/src/hotspot/share/memory/archiveBuilder.cpp @@ -24,8 +24,10 @@ #include "precompiled.hpp" #include "classfile/classLoaderDataShared.hpp" +#include "classfile/symbolTable.hpp" #include "classfile/systemDictionaryShared.hpp" #include "classfile/vmClasses.hpp" +#include "interpreter/abstractInterpreter.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/allStatic.hpp" @@ -40,13 +42,13 @@ #include "oops/objArrayKlass.hpp" #include "oops/oopHandle.inline.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/thread.hpp" #include "utilities/align.hpp" #include "utilities/bitMap.inline.hpp" +#include "utilities/formatBuffer.hpp" #include "utilities/hashtable.inline.hpp" -ArchiveBuilder* ArchiveBuilder::_singleton = NULL; -intx ArchiveBuilder::_buffer_to_target_delta = 0; - +ArchiveBuilder* ArchiveBuilder::_current = NULL; class AdapterHandlerEntry; class MethodTrampolineInfo { @@ -75,7 +77,7 @@ class AdapterToTrampoline : public ResourceHashtable< static AdapterToTrampoline* _adapter_to_trampoline = NULL; ArchiveBuilder::OtherROAllocMark::~OtherROAllocMark() { - char* newtop = ArchiveBuilder::singleton()->_ro_region->top(); + char* newtop = ArchiveBuilder::current()->_ro_region.top(); ArchiveBuilder::alloc_stats()->record_other_type(int(newtop - _oldtop), true); } @@ -165,30 +167,45 @@ void ArchiveBuilder::SourceObjList::relocate(int i, ArchiveBuilder* builder) { _ptrmap.iterate(&relocator, start, end); } -ArchiveBuilder::ArchiveBuilder(DumpRegion* mc_region, DumpRegion* rw_region, DumpRegion* ro_region) - : _rw_src_objs(), _ro_src_objs(), _src_obj_table(INITIAL_TABLE_SIZE) { - assert(_singleton == NULL, "must be"); - _singleton = this; - +ArchiveBuilder::ArchiveBuilder() : + _current_dump_space(NULL), + _buffer_bottom(NULL), + _last_verified_top(NULL), + _num_dump_regions_used(0), + _other_region_used_bytes(0), + _requested_static_archive_bottom(NULL), + _requested_static_archive_top(NULL), + _requested_dynamic_archive_bottom(NULL), + _requested_dynamic_archive_top(NULL), + _mapped_static_archive_bottom(NULL), + _mapped_static_archive_top(NULL), + _buffer_to_requested_delta(0), + _mc_region("mc", MAX_SHARED_DELTA), + _rw_region("rw", MAX_SHARED_DELTA), + _ro_region("ro", MAX_SHARED_DELTA), + _rw_src_objs(), + _ro_src_objs(), + _src_obj_table(INITIAL_TABLE_SIZE), + _num_instance_klasses(0), + _num_obj_array_klasses(0), + _num_type_array_klasses(0), + _total_closed_heap_region_size(0), + _total_open_heap_region_size(0), + _estimated_metaspaceobj_bytes(0), + _estimated_hashtable_bytes(0), + _estimated_trampoline_bytes(0) +{ _klasses = new (ResourceObj::C_HEAP, mtClassShared) GrowableArray(4 * K, mtClassShared); _symbols = new (ResourceObj::C_HEAP, mtClassShared) GrowableArray(256 * K, mtClassShared); _special_refs = new (ResourceObj::C_HEAP, mtClassShared) GrowableArray(24 * K, mtClassShared); - _num_instance_klasses = 0; - _num_obj_array_klasses = 0; - _num_type_array_klasses = 0; - _alloc_stats = new (ResourceObj::C_HEAP, mtClassShared) DumpAllocStats; - - _mc_region = mc_region; - _rw_region = rw_region; - _ro_region = ro_region; - - _estimated_metaspaceobj_bytes = 0; + assert(_current == NULL, "must be"); + _current = this; } ArchiveBuilder::~ArchiveBuilder() { - assert(_singleton == this, "must be"); - _singleton = NULL; + assert(_current == this, "must be"); + _current = NULL; clean_up_src_obj_table(); @@ -199,7 +216,10 @@ ArchiveBuilder::~ArchiveBuilder() { delete _klasses; delete _symbols; delete _special_refs; - delete _alloc_stats; +} + +bool ArchiveBuilder::is_dumping_full_module_graph() { + return DumpSharedSpaces && MetaspaceShared::use_full_module_graph(); } class GatherKlassesAndSymbols : public UniqueMetaspaceClosure { @@ -255,7 +275,7 @@ void ArchiveBuilder::gather_klasses_and_symbols() { GatherKlassesAndSymbols doit(this); iterate_roots(&doit, /*is_relocating_pointers=*/false); #if INCLUDE_CDS_JAVA_HEAP - if (DumpSharedSpaces && MetaspaceShared::use_full_module_graph()) { + if (is_dumping_full_module_graph()) { ClassLoaderDataShared::iterate_symbols(&doit); } #endif @@ -288,6 +308,10 @@ void ArchiveBuilder::gather_klasses_and_symbols() { // DynamicArchiveBuilder::sort_methods()). sort_symbols_and_fix_hash(); sort_klasses(); + + // TODO -- we need a proper estimate for the archived modules, etc, + // but this should be enough for now + _estimated_metaspaceobj_bytes += 200 * 1024 * 1024; } } @@ -319,6 +343,93 @@ void ArchiveBuilder::sort_klasses() { _klasses->sort(compare_klass_by_name); } +size_t ArchiveBuilder::estimate_archive_size() { + // size of the symbol table and two dictionaries, plus the RunTimeSharedClassInfo's + size_t symbol_table_est = SymbolTable::estimate_size_for_archive(); + size_t dictionary_est = SystemDictionaryShared::estimate_size_for_archive(); + _estimated_hashtable_bytes = symbol_table_est + dictionary_est; + + _estimated_trampoline_bytes = collect_method_trampolines(); + + size_t total = 0; + + total += _estimated_metaspaceobj_bytes; + total += _estimated_hashtable_bytes; + total += _estimated_trampoline_bytes; + + // allow fragmentation at the end of each dump region + total += _total_dump_regions * reserve_alignment(); + + log_info(cds)("_estimated_hashtable_bytes = " SIZE_FORMAT " + " SIZE_FORMAT " = " SIZE_FORMAT, + symbol_table_est, dictionary_est, _estimated_hashtable_bytes); + log_info(cds)("_estimated_metaspaceobj_bytes = " SIZE_FORMAT, _estimated_metaspaceobj_bytes); + log_info(cds)("_estimated_trampoline_bytes = " SIZE_FORMAT, _estimated_trampoline_bytes); + log_info(cds)("total estimate bytes = " SIZE_FORMAT, total); + + return align_up(total, reserve_alignment()); +} + +address ArchiveBuilder::reserve_buffer() { + size_t buffer_size = estimate_archive_size(); + ReservedSpace rs(buffer_size); + if (!rs.is_reserved()) { + log_error(cds)("Failed to reserve " SIZE_FORMAT " bytes of output buffer.", buffer_size); + vm_direct_exit(0); + } + + // buffer_bottom is the lowest address of the 3 core regions (mc, rw, ro) when + // we are copying the class metadata into the buffer. + address buffer_bottom = (address)rs.base(); + log_info(cds)("Reserved output buffer space at " PTR_FORMAT " [" SIZE_FORMAT " bytes]", + p2i(buffer_bottom), buffer_size); + _shared_rs = rs; + + _buffer_bottom = buffer_bottom; + _last_verified_top = buffer_bottom; + _current_dump_space = &_mc_region; + _num_dump_regions_used = 1; + _other_region_used_bytes = 0; + _current_dump_space->init(&_shared_rs, &_shared_vs); + + ArchivePtrMarker::initialize(&_ptrmap, &_shared_vs); + + // The bottom of the static archive should be mapped at this address by default. + _requested_static_archive_bottom = (address)MetaspaceShared::requested_base_address(); + + // The bottom of the archive (that I am writing now) should be mapped at this address by default. + address my_archive_requested_bottom; + + if (DumpSharedSpaces) { + my_archive_requested_bottom = _requested_static_archive_bottom; + } else { + _mapped_static_archive_bottom = (address)MetaspaceObj::shared_metaspace_base(); + _mapped_static_archive_top = (address)MetaspaceObj::shared_metaspace_top(); + assert(_mapped_static_archive_top >= _mapped_static_archive_bottom, "must be"); + size_t static_archive_size = _mapped_static_archive_top - _mapped_static_archive_bottom; + + // At run time, we will mmap the dynamic archive at my_archive_requested_bottom + _requested_static_archive_top = _requested_static_archive_bottom + static_archive_size; + my_archive_requested_bottom = align_up(_requested_static_archive_top, MetaspaceShared::reserved_space_alignment()); + + _requested_dynamic_archive_bottom = my_archive_requested_bottom; + } + + _buffer_to_requested_delta = my_archive_requested_bottom - _buffer_bottom; + + address my_archive_requested_top = my_archive_requested_bottom + buffer_size; + if (my_archive_requested_bottom < _requested_static_archive_bottom || + my_archive_requested_top <= _requested_static_archive_bottom) { + // Size overflow. + log_error(cds)("my_archive_requested_bottom = " INTPTR_FORMAT, p2i(my_archive_requested_bottom)); + log_error(cds)("my_archive_requested_top = " INTPTR_FORMAT, p2i(my_archive_requested_top)); + log_error(cds)("SharedBaseAddress (" INTPTR_FORMAT ") is too high. " + "Please rerun java -Xshare:dump with a lower value", p2i(_requested_static_archive_bottom)); + vm_direct_exit(0); + } + + return buffer_bottom; +} + void ArchiveBuilder::iterate_sorted_roots(MetaspaceClosure* it, bool is_relocating_pointers) { int i; @@ -418,6 +529,7 @@ void ArchiveBuilder::remember_embedded_pointer_in_copied_obj(MetaspaceClosure::R void ArchiveBuilder::gather_source_objs() { ResourceMark rm; log_info(cds)("Gathering all archivable objects ... "); + gather_klasses_and_symbols(); GatherSortedSourceObjs doit(this); iterate_sorted_roots(&doit, /*is_relocating_pointers=*/false); doit.finish(); @@ -463,16 +575,61 @@ ArchiveBuilder::FollowMode ArchiveBuilder::get_follow_mode(MetaspaceClosure::Ref } } +void ArchiveBuilder::start_dump_space(DumpRegion* next) { + address bottom = _last_verified_top; + address top = (address)(current_dump_space()->top()); + _other_region_used_bytes += size_t(top - bottom); + + current_dump_space()->pack(next); + _current_dump_space = next; + _num_dump_regions_used ++; + + _last_verified_top = (address)(current_dump_space()->top()); +} + +void ArchiveBuilder::verify_estimate_size(size_t estimate, const char* which) { + address bottom = _last_verified_top; + address top = (address)(current_dump_space()->top()); + size_t used = size_t(top - bottom) + _other_region_used_bytes; + int diff = int(estimate) - int(used); + + log_info(cds)("%s estimate = " SIZE_FORMAT " used = " SIZE_FORMAT "; diff = %d bytes", which, estimate, used, diff); + assert(diff >= 0, "Estimate is too small"); + + _last_verified_top = top; + _other_region_used_bytes = 0; +} + void ArchiveBuilder::dump_rw_region() { ResourceMark rm; log_info(cds)("Allocating RW objects ... "); - make_shallow_copies(_rw_region, &_rw_src_objs); + start_dump_space(&_rw_region); + make_shallow_copies(&_rw_region, &_rw_src_objs); + +#if INCLUDE_CDS_JAVA_HEAP + if (is_dumping_full_module_graph()) { + // Archive the ModuleEntry's and PackageEntry's of the 3 built-in loaders + char* start = rw_region()->top(); + ClassLoaderDataShared::allocate_archived_tables(); + alloc_stats()->record_modules(rw_region()->top() - start, /*read_only*/false); + } +#endif } void ArchiveBuilder::dump_ro_region() { ResourceMark rm; log_info(cds)("Allocating RO objects ... "); - make_shallow_copies(_ro_region, &_ro_src_objs); + + start_dump_space(&_ro_region); + make_shallow_copies(&_ro_region, &_ro_src_objs); + +#if INCLUDE_CDS_JAVA_HEAP + if (is_dumping_full_module_graph()) { + char* start = ro_region()->top(); + ClassLoaderDataShared::init_archived_tables(); + alloc_stats()->record_modules(ro_region()->top() - start, /*read_only*/true); + } +#endif } void ArchiveBuilder::make_shallow_copies(DumpRegion *dump_region, @@ -517,7 +674,7 @@ void ArchiveBuilder::make_shallow_copy(DumpRegion *dump_region, SourceObjInfo* s log_trace(cds)("Copy: " PTR_FORMAT " ==> " PTR_FORMAT " %d", p2i(src), p2i(dest), bytes); src_info->set_dumped_addr((address)dest); - _alloc_stats->record(ref->msotype(), int(newtop - oldtop), src_info->read_only()); + _alloc_stats.record(ref->msotype(), int(newtop - oldtop), src_info->read_only()); } address ArchiveBuilder::get_dumped_addr(address src_obj) const { @@ -580,22 +737,19 @@ class RefRelocator: public MetaspaceClosure { }; void ArchiveBuilder::relocate_roots() { + log_info(cds)("Relocating external roots ... "); ResourceMark rm; RefRelocator doit(this); iterate_sorted_roots(&doit, /*is_relocating_pointers=*/true); doit.finish(); + log_info(cds)("done"); } -void ArchiveBuilder::relocate_pointers() { - log_info(cds)("Relocating embedded pointers ... "); +void ArchiveBuilder::relocate_metaspaceobj_embedded_pointers() { + log_info(cds)("Relocating embedded pointers in core regions ... "); relocate_embedded_pointers(&_rw_src_objs); relocate_embedded_pointers(&_ro_src_objs); update_special_refs(); - - log_info(cds)("Relocating external roots ... "); - relocate_roots(); - - log_info(cds)("done"); } // We must relocate vmClasses::_klasses[] only after we have copied the @@ -630,9 +784,127 @@ void ArchiveBuilder::make_klasses_shareable() { if (log_is_enabled(Debug, cds, class)) { ResourceMark rm; - log_debug(cds, class)("klasses[%4d] = " PTR_FORMAT " %s", i, p2i(to_target(ik)), ik->external_name()); + log_debug(cds, class)("klasses[%4d] = " PTR_FORMAT " %s", i, p2i(to_requested(ik)), ik->external_name()); + } + } + } +} + +uintx ArchiveBuilder::buffer_to_offset(address p) const { + address requested_p = to_requested(p); + assert(requested_p >= _requested_static_archive_bottom, "must be"); + return requested_p - _requested_static_archive_bottom; +} + +uintx ArchiveBuilder::any_to_offset(address p) const { + if (is_in_mapped_static_archive(p)) { + assert(DynamicDumpSharedSpaces, "must be"); + return p - _mapped_static_archive_bottom; + } + return buffer_to_offset(p); +} + +// Update a Java object to point its Klass* to the new location after +// shared archive has been compacted. +void ArchiveBuilder::relocate_klass_ptr(oop o) { + assert(DumpSharedSpaces, "sanity"); + Klass* k = get_relocated_klass(o->klass()); + Klass* requested_k = to_requested(k); + narrowKlass nk = CompressedKlassPointers::encode_not_null(requested_k, _requested_static_archive_bottom); + o->set_narrow_klass(nk); +} + +// RelocateBufferToRequested --- Relocate all the pointers in mc/rw/ro, +// so that the archive can be mapped to the "requested" location without runtime relocation. +// +// - See ArchiveBuilder header for the definition of "buffer", "mapped" and "requested" +// - ArchivePtrMarker::ptrmap() marks all the pointers in the mc/rw/ro regions +// - Every pointer must have one of the following values: +// [a] NULL: +// No relocation is needed. Remove this pointer from ptrmap so we don't need to +// consider it at runtime. +// [b] Points into an object X which is inside the buffer: +// Adjust this pointer by _buffer_to_requested_delta, so it points to X +// when the archive is mapped at the requested location. +// [c] Points into an object Y which is inside mapped static archive: +// - This happens only during dynamic dump +// - Adjust this pointer by _mapped_to_requested_static_archive_delta, +// so it points to Y when the static archive is mapped at the requested location. +template +class RelocateBufferToRequested : public BitMapClosure { + ArchiveBuilder* _builder; + address _buffer_bottom; + intx _buffer_to_requested_delta; + intx _mapped_to_requested_static_archive_delta; + size_t _max_non_null_offset; + + public: + RelocateBufferToRequested(ArchiveBuilder* builder) { + _builder = builder; + _buffer_bottom = _builder->buffer_bottom(); + _buffer_to_requested_delta = builder->buffer_to_requested_delta(); + _mapped_to_requested_static_archive_delta = builder->requested_static_archive_bottom() - builder->mapped_static_archive_bottom(); + _max_non_null_offset = 0; + + address bottom = _builder->buffer_bottom(); + address top = _builder->buffer_top(); + address new_bottom = bottom + _buffer_to_requested_delta; + address new_top = top + _buffer_to_requested_delta; + log_debug(cds)("Relocating archive from [" INTPTR_FORMAT " - " INTPTR_FORMAT " ] to " + "[" INTPTR_FORMAT " - " INTPTR_FORMAT " ]", + p2i(bottom), p2i(top), + p2i(new_bottom), p2i(new_top)); + } + + bool do_bit(size_t offset) { + address* p = (address*)_buffer_bottom + offset; + assert(_builder->is_in_buffer_space(p), "pointer must live in buffer space"); + + if (*p == NULL) { + // todo -- clear bit, etc + ArchivePtrMarker::ptrmap()->clear_bit(offset); + } else { + if (STATIC_DUMP) { + assert(_builder->is_in_buffer_space(*p), "old pointer must point inside buffer space"); + *p += _buffer_to_requested_delta; + assert(_builder->is_in_requested_static_archive(*p), "new pointer must point inside requested archive"); + } else { + if (_builder->is_in_buffer_space(*p)) { + *p += _buffer_to_requested_delta; + // assert is in requested dynamic archive + } else { + assert(_builder->is_in_mapped_static_archive(*p), "old pointer must point inside buffer space or mapped static archive"); + *p += _mapped_to_requested_static_archive_delta; + assert(_builder->is_in_requested_static_archive(*p), "new pointer must point inside requested archive"); + } } + _max_non_null_offset = offset; } + + return true; // keep iterating + } + + void doit() { + ArchivePtrMarker::ptrmap()->iterate(this); + ArchivePtrMarker::compact(_max_non_null_offset); + } +}; + + +void ArchiveBuilder::relocate_to_requested() { + ro_region()->pack(); + + size_t my_archive_size = buffer_top() - buffer_bottom(); + + if (DumpSharedSpaces) { + _requested_static_archive_top = _requested_static_archive_bottom + my_archive_size; + RelocateBufferToRequested patcher(this); + patcher.doit(); + } else { + assert(DynamicDumpSharedSpaces, "must be"); + _requested_dynamic_archive_top = _requested_dynamic_archive_bottom + my_archive_size; + RelocateBufferToRequested patcher(this); + patcher.doit(); } } @@ -649,9 +921,9 @@ void ArchiveBuilder::make_klasses_shareable() { // consistency, we log everything using runtime addresses. class ArchiveBuilder::CDSMapLogger : AllStatic { static intx buffer_to_runtime_delta() { - // Translate the buffers used by the MC/RW/RO regions to their eventual locations + // Translate the buffers used by the MC/RW/RO regions to their eventual (requested) locations // at runtime. - return _buffer_to_target_delta + MetaspaceShared::final_delta(); + return ArchiveBuilder::current()->buffer_to_requested_delta(); } // mc/rw/ro regions only @@ -790,9 +1062,9 @@ class ArchiveBuilder::CDSMapLogger : AllStatic { write_header(mapinfo); write_data(header, header_end, 0); - DumpRegion* mc_region = builder->_mc_region; - DumpRegion* rw_region = builder->_rw_region; - DumpRegion* ro_region = builder->_ro_region; + DumpRegion* mc_region = &builder->_mc_region; + DumpRegion* rw_region = &builder->_rw_region; + DumpRegion* ro_region = &builder->_ro_region; address mc = address(mc_region->base()); address mc_end = address(mc_region->end()); @@ -820,18 +1092,8 @@ class ArchiveBuilder::CDSMapLogger : AllStatic { } }; -void ArchiveBuilder::write_cds_map_to_log(FileMapInfo* mapinfo, - GrowableArray *closed_heap_regions, - GrowableArray *open_heap_regions, - char* bitmap, size_t bitmap_size_in_bytes) { - if (log_is_enabled(Info, cds, map)) { - CDSMapLogger::write(this, mapinfo, closed_heap_regions, open_heap_regions, - bitmap, bitmap_size_in_bytes); - } -} - -void ArchiveBuilder::print_stats(int ro_all, int rw_all, int mc_all) { - _alloc_stats->print_stats(ro_all, rw_all, mc_all); +void ArchiveBuilder::print_stats() { + _alloc_stats.print_stats(int(_ro_region.used()), int(_rw_region.used()), int(_mc_region.used())); } void ArchiveBuilder::clean_up_src_obj_table() { @@ -839,6 +1101,20 @@ void ArchiveBuilder::clean_up_src_obj_table() { _src_obj_table.iterate(&cleaner); } +void ArchiveBuilder::init_mc_region() { + if (DumpSharedSpaces) { // these are needed only for static archive + // We don't want any valid object to be at the very bottom of the archive. + // See ArchivePtrMarker::mark_pointer(). + mc_region()->allocate(16); + + size_t trampoline_size = SharedRuntime::trampoline_size(); + size_t buf_size = (size_t)AbstractInterpreter::number_of_method_entries * trampoline_size; + MetaspaceShared::set_i2i_entry_code_buffers((address)mc_region()->allocate(buf_size)); + } + + allocate_method_trampolines(); +} + void ArchiveBuilder::allocate_method_trampolines_for(InstanceKlass* ik) { if (ik->methods() != NULL) { for (int j = 0; j < ik->methods()->length(); j++) { @@ -849,13 +1125,13 @@ void ArchiveBuilder::allocate_method_trampolines_for(InstanceKlass* ik) { 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())); + (address)mc_region()->allocate(SharedRuntime::trampoline_size())); info->set_c2i_inline_ro_entry_trampoline( - (address)MetaspaceShared::misc_code_space_alloc(SharedRuntime::trampoline_size())); + (address)mc_region()->allocate(SharedRuntime::trampoline_size())); info->set_c2i_inline_entry_trampoline( - (address)MetaspaceShared::misc_code_space_alloc(SharedRuntime::trampoline_size())); + (address)mc_region()->allocate(SharedRuntime::trampoline_size())); info->set_adapter_trampoline( - (AdapterHandlerEntry**)MetaspaceShared::misc_code_space_alloc(sizeof(AdapterHandlerEntry*))); + (AdapterHandlerEntry**)mc_region()->allocate(sizeof(AdapterHandlerEntry*))); } } } @@ -874,7 +1150,7 @@ void ArchiveBuilder::allocate_method_trampolines() { // 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 ArchiveBuilder::collect_method_trampolines() { size_t total = 0; size_t each_method_bytes = align_up(SharedRuntime::trampoline_size(), BytesPerWord) * 3 + @@ -930,3 +1206,126 @@ void ArchiveBuilder::update_method_trampolines() { } } } + +void ArchiveBuilder::write_archive(FileMapInfo* mapinfo, + GrowableArray* closed_heap_regions, + GrowableArray* open_heap_regions, + GrowableArray* closed_heap_oopmaps, + GrowableArray* open_heap_oopmaps) { + // Make sure NUM_CDS_REGIONS (exported in cds.h) agrees with + // MetaspaceShared::n_regions (internal to hotspot). + assert(NUM_CDS_REGIONS == MetaspaceShared::n_regions, "sanity"); + + // mc contains the trampoline code for method entries, which are patched at run time, + // so it needs to be read/write. + write_region(mapinfo, MetaspaceShared::mc, &_mc_region, /*read_only=*/false,/*allow_exec=*/true); + write_region(mapinfo, MetaspaceShared::rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false); + write_region(mapinfo, MetaspaceShared::ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false); + + size_t bitmap_size_in_bytes; + char* bitmap = mapinfo->write_bitmap_region(ArchivePtrMarker::ptrmap(), closed_heap_oopmaps, open_heap_oopmaps, + bitmap_size_in_bytes); + + if (closed_heap_regions != NULL) { + _total_closed_heap_region_size = mapinfo->write_archive_heap_regions( + closed_heap_regions, + closed_heap_oopmaps, + MetaspaceShared::first_closed_archive_heap_region, + MetaspaceShared::max_closed_archive_heap_region); + _total_open_heap_region_size = mapinfo->write_archive_heap_regions( + open_heap_regions, + open_heap_oopmaps, + MetaspaceShared::first_open_archive_heap_region, + MetaspaceShared::max_open_archive_heap_region); + } + + print_region_stats(mapinfo, closed_heap_regions, open_heap_regions); + + mapinfo->set_requested_base((char*)MetaspaceShared::requested_base_address()); + mapinfo->set_header_crc(mapinfo->compute_header_crc()); + mapinfo->write_header(); + mapinfo->close(); + + if (log_is_enabled(Info, cds)) { + print_stats(); + } + + if (log_is_enabled(Info, cds, map)) { + CDSMapLogger::write(this, mapinfo, closed_heap_regions, open_heap_regions, + bitmap, bitmap_size_in_bytes); + } + FREE_C_HEAP_ARRAY(char, bitmap); +} + +void ArchiveBuilder::write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, bool read_only, bool allow_exec) { + mapinfo->write_region(region_idx, dump_region->base(), dump_region->used(), read_only, allow_exec); +} + +void ArchiveBuilder::print_region_stats(FileMapInfo *mapinfo, + GrowableArray* closed_heap_regions, + GrowableArray* open_heap_regions) { + // Print statistics of all the regions + const size_t bitmap_used = mapinfo->space_at(MetaspaceShared::bm)->used(); + const size_t bitmap_reserved = mapinfo->space_at(MetaspaceShared::bm)->used_aligned(); + const size_t total_reserved = _ro_region.reserved() + _rw_region.reserved() + + _mc_region.reserved() + + bitmap_reserved + + _total_closed_heap_region_size + + _total_open_heap_region_size; + const size_t total_bytes = _ro_region.used() + _rw_region.used() + + _mc_region.used() + + bitmap_used + + _total_closed_heap_region_size + + _total_open_heap_region_size; + const double total_u_perc = percent_of(total_bytes, total_reserved); + + _mc_region.print(total_reserved); + _rw_region.print(total_reserved); + _ro_region.print(total_reserved); + + print_bitmap_region_stats(bitmap_used, total_reserved); + + if (closed_heap_regions != NULL) { + print_heap_region_stats(closed_heap_regions, "ca", total_reserved); + print_heap_region_stats(open_heap_regions, "oa", total_reserved); + } + + log_debug(cds)("total : " SIZE_FORMAT_W(9) " [100.0%% of total] out of " SIZE_FORMAT_W(9) " bytes [%5.1f%% used]", + total_bytes, total_reserved, total_u_perc); +} + +void ArchiveBuilder::print_bitmap_region_stats(size_t size, size_t total_size) { + log_debug(cds)("bm space: " SIZE_FORMAT_W(9) " [ %4.1f%% of total] out of " SIZE_FORMAT_W(9) " bytes [100.0%% used]", + size, size/double(total_size)*100.0, size); +} + +void ArchiveBuilder::print_heap_region_stats(GrowableArray *heap_mem, + const char *name, size_t total_size) { + int arr_len = heap_mem == NULL ? 0 : heap_mem->length(); + for (int i = 0; i < arr_len; i++) { + char* start = (char*)heap_mem->at(i).start(); + size_t size = heap_mem->at(i).byte_size(); + char* top = start + size; + log_debug(cds)("%s%d space: " SIZE_FORMAT_W(9) " [ %4.1f%% of total] out of " SIZE_FORMAT_W(9) " bytes [100.0%% used] at " INTPTR_FORMAT, + name, i, size, size/double(total_size)*100.0, size, p2i(start)); + } +} + +void ArchiveBuilder::report_out_of_space(const char* name, size_t needed_bytes) { + // This is highly unlikely to happen on 64-bits because we have reserved a 4GB space. + // On 32-bit we reserve only 256MB so you could run out of space with 100,000 classes + // or so. + _mc_region.print_out_of_space_msg(name, needed_bytes); + _rw_region.print_out_of_space_msg(name, needed_bytes); + _ro_region.print_out_of_space_msg(name, needed_bytes); + + vm_exit_during_initialization(err_msg("Unable to allocate from '%s' region", name), + "Please reduce the number of shared classes."); +} + + +#ifndef PRODUCT +void ArchiveBuilder::assert_is_vm_thread() { + assert(Thread::current()->is_VM_thread(), "ArchiveBuilder should be used only inside the VMThread"); +} +#endif diff --git a/src/hotspot/share/memory/archiveBuilder.hpp b/src/hotspot/share/memory/archiveBuilder.hpp index 235b13ae832..d91d89aabb2 100644 --- a/src/hotspot/share/memory/archiveBuilder.hpp +++ b/src/hotspot/share/memory/archiveBuilder.hpp @@ -26,21 +26,70 @@ #define SHARE_MEMORY_ARCHIVEBUILDER_HPP #include "memory/archiveUtils.hpp" +#include "memory/dumpAllocStats.hpp" #include "memory/metaspaceClosure.hpp" +#include "oops/array.hpp" #include "oops/klass.hpp" +#include "runtime/os.hpp" #include "utilities/bitMap.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.hpp" #include "utilities/resourceHash.hpp" +struct ArchiveHeapOopmapInfo; class CHeapBitMap; -class DumpAllocStats; class FileMapInfo; class Klass; class MemRegion; class Symbol; +// Metaspace::allocate() requires that all blocks must be aligned with KlassAlignmentInBytes. +// We enforce the same alignment rule in blocks allocated from the shared space. +const int SharedSpaceObjectAlignment = KlassAlignmentInBytes; + +// Overview of CDS archive creation (for both static and dynamic dump): +// +// [1] Load all classes (static dump: from the classlist, dynamic dump: as part of app execution) +// [2] Allocate "output buffer" +// [3] Copy contents of the 3 "core" regions (mc/rw/ro) into the output buffer. +// - mc region: +// allocate_method_trampolines(); +// allocate the cpp vtables (static dump only) +// - memcpy the MetaspaceObjs into rw/ro: +// dump_rw_region(); +// dump_ro_region(); +// - fix all the pointers in the MetaspaceObjs to point to the copies +// relocate_metaspaceobj_embedded_pointers() +// [4] Copy symbol table, dictionary, etc, into the ro region +// [5] Relocate all the pointers in mc/rw/ro, so that the archive can be mapped to +// the "requested" location without runtime relocation. See relocate_to_requested() class ArchiveBuilder : public StackObj { +protected: + DumpRegion* _current_dump_space; + address _buffer_bottom; // for writing the contents of mc/rw/ro regions + address _last_verified_top; + int _num_dump_regions_used; + size_t _other_region_used_bytes; + + // These are the addresses where we will request the static and dynamic archives to be + // mapped at run time. If the request fails (due to ASLR), we will map the archives at + // os-selected addresses. + address _requested_static_archive_bottom; // This is determined solely by the value of + // SharedBaseAddress during -Xshare:dump. + address _requested_static_archive_top; + address _requested_dynamic_archive_bottom; // Used only during dynamic dump. It's placed + // immediately above _requested_static_archive_top. + address _requested_dynamic_archive_top; + + // (Used only during dynamic dump) where the static archive is actually mapped. This + // may be different than _requested_static_archive_{bottom,top} due to ASLR + address _mapped_static_archive_bottom; + address _mapped_static_archive_top; + + intx _buffer_to_requested_delta; + + DumpRegion* current_dump_space() const { return _current_dump_space; } + public: enum FollowMode { make_a_copy, point_to_it, set_to_null @@ -148,9 +197,13 @@ class ArchiveBuilder : public StackObj { static const int INITIAL_TABLE_SIZE = 15889; static const int MAX_TABLE_SIZE = 1000000; - DumpRegion* _mc_region; - DumpRegion* _rw_region; - DumpRegion* _ro_region; + ReservedSpace _shared_rs; + VirtualSpace _shared_vs; + + DumpRegion _mc_region; + DumpRegion _rw_region; + DumpRegion _ro_region; + CHeapBitMap _ptrmap; // bitmap used by ArchivePtrMarker SourceObjList _rw_src_objs; // objs to put in rw region SourceObjList _ro_src_objs; // objs to put in ro region @@ -163,10 +216,19 @@ class ArchiveBuilder : public StackObj { int _num_instance_klasses; int _num_obj_array_klasses; int _num_type_array_klasses; - DumpAllocStats* _alloc_stats; + DumpAllocStats _alloc_stats; + size_t _total_closed_heap_region_size; + size_t _total_open_heap_region_size; + + void print_region_stats(FileMapInfo *map_info, + GrowableArray* closed_heap_regions, + GrowableArray* open_heap_regions); + void print_bitmap_region_stats(size_t size, size_t total_size); + void print_heap_region_stats(GrowableArray *heap_mem, + const char *name, size_t total_size); // For global access. - static ArchiveBuilder* _singleton; + static ArchiveBuilder* _current; public: // Use this when you allocate space with MetaspaceShare::read_only_space_alloc() @@ -176,12 +238,13 @@ class ArchiveBuilder : public StackObj { char* _oldtop; public: OtherROAllocMark() { - _oldtop = _singleton->_ro_region->top(); + _oldtop = _current->_ro_region.top(); } ~OtherROAllocMark(); }; private: + bool is_dumping_full_module_graph(); FollowMode get_follow_mode(MetaspaceClosure::Ref *ref); void iterate_sorted_roots(MetaspaceClosure* it, bool is_relocating_pointers); @@ -195,49 +258,92 @@ class ArchiveBuilder : public StackObj { void update_special_refs(); void relocate_embedded_pointers(SourceObjList* src_objs); - void relocate_roots(); bool is_excluded(Klass* k); void clean_up_src_obj_table(); + protected: virtual void iterate_roots(MetaspaceClosure* it, bool is_relocating_pointers) = 0; // Conservative estimate for number of bytes needed for: size_t _estimated_metaspaceobj_bytes; // all archived MetaspaceObj's. + size_t _estimated_hashtable_bytes; // symbol table and dictionaries + size_t _estimated_trampoline_bytes; // method entry trampolines -protected: - DumpRegion* _current_dump_space; - address _alloc_bottom; + static const int _total_dump_regions = 3; - DumpRegion* current_dump_space() const { return _current_dump_space; } + size_t estimate_archive_size(); + + static size_t reserve_alignment() { + return os::vm_allocation_granularity(); + } + + void start_dump_space(DumpRegion* next); + void verify_estimate_size(size_t estimate, const char* which); public: - void set_current_dump_space(DumpRegion* r) { _current_dump_space = r; } + address reserve_buffer(); + + address buffer_bottom() const { return _buffer_bottom; } + address buffer_top() const { return (address)current_dump_space()->top(); } + address requested_static_archive_bottom() const { return _requested_static_archive_bottom; } + address mapped_static_archive_bottom() const { return _mapped_static_archive_bottom; } + intx buffer_to_requested_delta() const { return _buffer_to_requested_delta; } bool is_in_buffer_space(address p) const { - return (_alloc_bottom <= p && p < (address)current_dump_space()->top()); + return (buffer_bottom() <= p && p < buffer_top()); } - template bool is_in_target_space(T target_obj) const { - address buff_obj = address(target_obj) - _buffer_to_target_delta; - return is_in_buffer_space(buff_obj); + template bool is_in_requested_static_archive(T p) const { + return _requested_static_archive_bottom <= (address)p && (address)p < _requested_static_archive_top; + } + + template bool is_in_mapped_static_archive(T p) const { + return _mapped_static_archive_bottom <= (address)p && (address)p < _mapped_static_archive_top; } template bool is_in_buffer_space(T obj) const { return is_in_buffer_space(address(obj)); } - template T to_target_no_check(T obj) const { - return (T)(address(obj) + _buffer_to_target_delta); + template T to_requested(T obj) const { + assert(is_in_buffer_space(obj), "must be"); + return (T)(address(obj) + _buffer_to_requested_delta); } - template T to_target(T obj) const { - assert(is_in_buffer_space(obj), "must be"); - return (T)(address(obj) + _buffer_to_target_delta); + static intx get_buffer_to_requested_delta() { + return current()->buffer_to_requested_delta(); } public: - ArchiveBuilder(DumpRegion* mc_region, DumpRegion* rw_region, DumpRegion* ro_region); + static const uintx MAX_SHARED_DELTA = 0x7FFFFFFF; + + // The address p points to an object inside the output buffer. When the archive is mapped + // at the requested address, what's the offset of this object from _requested_static_archive_bottom? + uintx buffer_to_offset(address p) const; + + // Same as buffer_to_offset, except that the address p points to either (a) an object + // inside the output buffer, or (b), an object in the currently mapped static archive. + uintx any_to_offset(address p) const; + + template + u4 buffer_to_offset_u4(T p) const { + uintx offset = buffer_to_offset((address)p); + guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset"); + return (u4)offset; + } + + template + u4 any_to_offset_u4(T p) const { + uintx offset = any_to_offset((address)p); + guarantee(offset <= MAX_SHARED_DELTA, "must be 32-bit offset"); + return (u4)offset; + } + + static void assert_is_vm_thread() PRODUCT_RETURN; + +public: + ArchiveBuilder(); ~ArchiveBuilder(); void gather_klasses_and_symbols(); @@ -249,15 +355,57 @@ class ArchiveBuilder : public StackObj { } void remember_embedded_pointer_in_copied_obj(MetaspaceClosure::Ref* enclosing_ref, MetaspaceClosure::Ref* ref); + DumpRegion* mc_region() { return &_mc_region; } + DumpRegion* rw_region() { return &_rw_region; } + DumpRegion* ro_region() { return &_ro_region; } + + static char* mc_region_alloc(size_t num_bytes) { + return current()->mc_region()->allocate(num_bytes); + } + static char* rw_region_alloc(size_t num_bytes) { + return current()->rw_region()->allocate(num_bytes); + } + static char* ro_region_alloc(size_t num_bytes) { + return current()->ro_region()->allocate(num_bytes); + } + + template + static Array* new_ro_array(int length) { + size_t byte_size = Array::byte_sizeof(length, sizeof(T)); + Array* array = (Array*)ro_region_alloc(byte_size); + array->initialize(length); + return array; + } + + template + static Array* new_rw_array(int length) { + size_t byte_size = Array::byte_sizeof(length, sizeof(T)); + Array* array = (Array*)rw_region_alloc(byte_size); + array->initialize(length); + return array; + } + + template + static size_t ro_array_bytesize(int length) { + size_t byte_size = Array::byte_sizeof(length, sizeof(T)); + return align_up(byte_size, SharedSpaceObjectAlignment); + } + + void init_mc_region(); void dump_rw_region(); void dump_ro_region(); - void relocate_pointers(); + void relocate_metaspaceobj_embedded_pointers(); + void relocate_roots(); void relocate_vm_classes(); void make_klasses_shareable(); - void write_cds_map_to_log(FileMapInfo* mapinfo, - GrowableArray *closed_heap_regions, - GrowableArray *open_heap_regions, - char* bitmap, size_t bitmap_size_in_bytes); + void relocate_to_requested(); + void write_archive(FileMapInfo* mapinfo, + GrowableArray* closed_heap_regions, + GrowableArray* open_heap_regions, + GrowableArray* closed_heap_oopmaps, + GrowableArray* open_heap_oopmaps); + void write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, + bool read_only, bool allow_exec); address get_dumped_addr(address src_obj) const; @@ -265,34 +413,48 @@ class ArchiveBuilder : public StackObj { GrowableArray* klasses() const { return _klasses; } GrowableArray* symbols() const { return _symbols; } - static ArchiveBuilder* singleton() { - assert(_singleton != NULL, "ArchiveBuilder must be active"); - return _singleton; + static bool is_active() { + return (_current != NULL); + } + + static ArchiveBuilder* current() { + assert_is_vm_thread(); + assert(_current != NULL, "ArchiveBuilder must be active"); + return _current; } static DumpAllocStats* alloc_stats() { - return singleton()->_alloc_stats; + return &(current()->_alloc_stats); } + static CompactHashtableStats* symbol_stats() { + return alloc_stats()->symbol_stats(); + } + + static CompactHashtableStats* string_stats() { + return alloc_stats()->string_stats(); + } + + void relocate_klass_ptr(oop o); + static Klass* get_relocated_klass(Klass* orig_klass) { - Klass* klass = (Klass*)singleton()->get_dumped_addr((address)orig_klass); + Klass* klass = (Klass*)current()->get_dumped_addr((address)orig_klass); assert(klass != NULL && klass->is_klass(), "must be"); return klass; } static Symbol* get_relocated_symbol(Symbol* orig_symbol) { - return (Symbol*)singleton()->get_dumped_addr((address)orig_symbol); + return (Symbol*)current()->get_dumped_addr((address)orig_symbol); } - void print_stats(int ro_all, int rw_all, int mc_all); - static intx _buffer_to_target_delta; + void print_stats(); + void report_out_of_space(const char* name, size_t needed_bytes); // Method trampolines related functions + size_t collect_method_trampolines(); 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/archiveUtils.cpp b/src/hotspot/share/memory/archiveUtils.cpp index 3f1d59f1aed..3195144bed6 100644 --- a/src/hotspot/share/memory/archiveUtils.cpp +++ b/src/hotspot/share/memory/archiveUtils.cpp @@ -28,6 +28,7 @@ #include "classfile/systemDictionaryShared.hpp" #include "classfile/vmClasses.hpp" #include "interpreter/bootstrapInfo.hpp" +#include "memory/archiveBuilder.hpp" #include "memory/archiveUtils.hpp" #include "memory/dynamicArchive.hpp" #include "memory/filemap.hpp" @@ -39,14 +40,13 @@ #include "utilities/bitMap.inline.hpp" CHeapBitMap* ArchivePtrMarker::_ptrmap = NULL; -address* ArchivePtrMarker::_ptr_base; -address* ArchivePtrMarker::_ptr_end; +VirtualSpace* ArchivePtrMarker::_vs; + bool ArchivePtrMarker::_compacted; -void ArchivePtrMarker::initialize(CHeapBitMap* ptrmap, address* ptr_base, address* ptr_end) { +void ArchivePtrMarker::initialize(CHeapBitMap* ptrmap, VirtualSpace* vs) { assert(_ptrmap == NULL, "initialize only once"); - _ptr_base = ptr_base; - _ptr_end = ptr_end; + _vs = vs; _compacted = false; _ptrmap = ptrmap; @@ -65,17 +65,17 @@ void ArchivePtrMarker::mark_pointer(address* ptr_loc) { assert(_ptrmap != NULL, "not initialized"); assert(!_compacted, "cannot mark anymore"); - if (_ptr_base <= ptr_loc && ptr_loc < _ptr_end) { + if (ptr_base() <= ptr_loc && ptr_loc < ptr_end()) { address value = *ptr_loc; // We don't want any pointer that points to very bottom of the archive, otherwise when // MetaspaceShared::default_base_address()==0, we can't distinguish between a pointer // to nothing (NULL) vs a pointer to an objects that happens to be at the very bottom // of the archive. - assert(value != (address)_ptr_base, "don't point to the bottom of the archive"); + assert(value != (address)ptr_base(), "don't point to the bottom of the archive"); if (value != NULL) { assert(uintx(ptr_loc) % sizeof(intptr_t) == 0, "pointers must be stored in aligned addresses"); - size_t idx = ptr_loc - _ptr_base; + size_t idx = ptr_loc - ptr_base(); if (_ptrmap->size() <= idx) { _ptrmap->resize((idx + 1) * 2); } @@ -90,9 +90,9 @@ void ArchivePtrMarker::clear_pointer(address* ptr_loc) { assert(_ptrmap != NULL, "not initialized"); assert(!_compacted, "cannot clear anymore"); - assert(_ptr_base <= ptr_loc && ptr_loc < _ptr_end, "must be"); + assert(ptr_base() <= ptr_loc && ptr_loc < ptr_end(), "must be"); assert(uintx(ptr_loc) % sizeof(intptr_t) == 0, "pointers must be stored in aligned addresses"); - size_t idx = ptr_loc - _ptr_base; + size_t idx = ptr_loc - ptr_base(); assert(idx < _ptrmap->size(), "cannot clear pointers that have not been marked"); _ptrmap->clear_bit(idx); //tty->print_cr("Clearing pointer [" PTR_FORMAT "] -> " PTR_FORMAT " @ " SIZE_FORMAT_W(5), p2i(ptr_loc), p2i(*ptr_loc), idx); @@ -131,7 +131,7 @@ class ArchivePtrBitmapCleaner: public BitMapClosure { void ArchivePtrMarker::compact(address relocatable_base, address relocatable_end) { assert(!_compacted, "cannot compact again"); - ArchivePtrBitmapCleaner cleaner(_ptrmap, _ptr_base, relocatable_base, relocatable_end); + ArchivePtrBitmapCleaner cleaner(_ptrmap, ptr_base(), relocatable_base, relocatable_end); _ptrmap->iterate(&cleaner); compact(cleaner.max_non_null_offset()); } @@ -146,18 +146,16 @@ char* DumpRegion::expand_top_to(char* newtop) { assert(is_allocatable(), "must be initialized and not packed"); assert(newtop >= _top, "must not grow backwards"); if (newtop > _end) { - MetaspaceShared::report_out_of_space(_name, newtop - _top); + ArchiveBuilder::current()->report_out_of_space(_name, newtop - _top); ShouldNotReachHere(); } - if (_rs == MetaspaceShared::shared_rs()) { - uintx delta; - if (DynamicDumpSharedSpaces) { - delta = DynamicArchive::object_delta_uintx(newtop); - } else { - delta = MetaspaceShared::object_delta_uintx(newtop); - } - if (delta > MAX_SHARED_DELTA) { + commit_to(newtop); + _top = newtop; + + if (_max_delta > 0) { + uintx delta = ArchiveBuilder::current()->buffer_to_offset((address)(newtop-1)); + if (delta > _max_delta) { // This is just a sanity check and should not appear in any real world usage. This // happens only if you allocate more than 2GB of shared objects and would require // millions of shared classes. @@ -166,11 +164,42 @@ char* DumpRegion::expand_top_to(char* newtop) { } } - MetaspaceShared::commit_to(_rs, _vs, newtop); - _top = newtop; return _top; } +void DumpRegion::commit_to(char* newtop) { + Arguments::assert_is_dumping_archive(); + char* base = _rs->base(); + size_t need_committed_size = newtop - base; + size_t has_committed_size = _vs->committed_size(); + if (need_committed_size < has_committed_size) { + return; + } + + size_t min_bytes = need_committed_size - has_committed_size; + size_t preferred_bytes = 1 * M; + size_t uncommitted = _vs->reserved_size() - has_committed_size; + + size_t commit = MAX2(min_bytes, preferred_bytes); + commit = MIN2(commit, uncommitted); + assert(commit <= uncommitted, "sanity"); + + if (!_vs->expand_by(commit, false)) { + vm_exit_during_initialization(err_msg("Failed to expand shared space to " SIZE_FORMAT " bytes", + need_committed_size)); + } + + const char* which; + if (_rs->base() == (char*)MetaspaceShared::symbol_rs_base()) { + which = "symbol"; + } else { + which = "shared"; + } + log_debug(cds)("Expanding %s spaces by " SIZE_FORMAT_W(7) " bytes [total " SIZE_FORMAT_W(9) " bytes ending at %p]", + which, commit, _vs->actual_committed_size(), _vs->high()); +} + + char* DumpRegion::allocate(size_t num_bytes) { char* p = (char*)align_up(_top, (size_t)SharedSpaceObjectAlignment); char* newtop = p + align_up(num_bytes, (size_t)SharedSpaceObjectAlignment); @@ -193,7 +222,7 @@ void DumpRegion::append_intptr_t(intptr_t n, bool need_to_mark) { void DumpRegion::print(size_t total_bytes) const { log_debug(cds)("%-3s space: " SIZE_FORMAT_W(9) " [ %4.1f%% of total] out of " SIZE_FORMAT_W(9) " bytes [%5.1f%% used] at " INTPTR_FORMAT, _name, used(), percent_of(used(), total_bytes), reserved(), percent_of(used(), reserved()), - p2i(_base + MetaspaceShared::final_delta())); + p2i(ArchiveBuilder::current()->to_requested(_base))); } void DumpRegion::print_out_of_space_msg(const char* failing_region, size_t needed_bytes) { diff --git a/src/hotspot/share/memory/archiveUtils.hpp b/src/hotspot/share/memory/archiveUtils.hpp index 4f2ae6f6276..4121b955e43 100644 --- a/src/hotspot/share/memory/archiveUtils.hpp +++ b/src/hotspot/share/memory/archiveUtils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "logging/log.hpp" #include "memory/iterator.hpp" +#include "memory/virtualspace.hpp" #include "runtime/arguments.hpp" #include "utilities/bitMap.hpp" @@ -39,15 +40,18 @@ class VirtualSpace; // mark_pointer(/*ptr_loc=*/&k->_name). It's required that (_prt_base <= ptr_loc < _ptr_end). _ptr_base is // fixed, but _ptr_end can be expanded as more objects are dumped. class ArchivePtrMarker : AllStatic { - static CHeapBitMap* _ptrmap; - static address* _ptr_base; - static address* _ptr_end; + static CHeapBitMap* _ptrmap; + static VirtualSpace* _vs; // Once _ptrmap is compacted, we don't allow bit marking anymore. This is to // avoid unintentional copy operations after the bitmap has been finalized and written. static bool _compacted; + + static address* ptr_base() { return (address*)_vs->low(); } // committed lower bound (inclusive) + static address* ptr_end() { return (address*)_vs->high(); } // committed upper bound (exclusive) + public: - static void initialize(CHeapBitMap* ptrmap, address* ptr_base, address* ptr_end); + static void initialize(CHeapBitMap* ptrmap, VirtualSpace* vs); static void mark_pointer(address* ptr_loc); static void clear_pointer(address* ptr_loc); static void compact(address relocatable_base, address relocatable_end); @@ -64,11 +68,6 @@ class ArchivePtrMarker : AllStatic { mark_pointer(ptr_loc); } - static void expand_ptr_end(address *new_ptr_end) { - assert(_ptr_end <= new_ptr_end, "must be"); - _ptr_end = new_ptr_end; - } - static CHeapBitMap* ptrmap() { return _ptrmap; } @@ -85,7 +84,6 @@ class ArchivePtrMarker : AllStatic { // If the archive ends up being mapped at a different address (e.g. 0x810000000), SharedDataRelocator // is used to shift each marked pointer by a delta (0x10000000 in this example), so that it points to // the actually mapped location of the target object. -template class SharedDataRelocator: public BitMapClosure { // for all (address** p), where (is_marked(p) && _patch_base <= p && p < _patch_end) { *p += delta; } @@ -104,17 +102,10 @@ class SharedDataRelocator: public BitMapClosure { // How much to relocate for each pointer. intx _delta; - // The following fields are used only when COMPACTING == true; - // The highest offset (inclusive) in the bitmap that contains a non-null pointer. - // This is used at dump time to reduce the size of the bitmap (which may have been over-allocated). - size_t _max_non_null_offset; - CHeapBitMap* _ptrmap; - public: SharedDataRelocator(address* patch_base, address* patch_end, address valid_old_base, address valid_old_end, - address valid_new_base, address valid_new_end, intx delta, - CHeapBitMap* ptrmap = NULL) : + address valid_new_base, address valid_new_end, intx delta) : _patch_base(patch_base), _patch_end(patch_end), _valid_old_base(valid_old_base), _valid_old_end(valid_old_end), _valid_new_base(valid_new_base), _valid_new_end(valid_new_end), @@ -125,23 +116,9 @@ class SharedDataRelocator: public BitMapClosure { log_debug(cds, reloc)("SharedDataRelocator::_valid_old_end = " PTR_FORMAT, p2i(_valid_old_end)); log_debug(cds, reloc)("SharedDataRelocator::_valid_new_base = " PTR_FORMAT, p2i(_valid_new_base)); log_debug(cds, reloc)("SharedDataRelocator::_valid_new_end = " PTR_FORMAT, p2i(_valid_new_end)); - if (COMPACTING) { - assert(ptrmap != NULL, "must be"); - _max_non_null_offset = 0; - _ptrmap = ptrmap; - } else { - // Don't touch the _max_non_null_offset and _ptrmap fields. Hopefully a good C++ compiler can - // elide them. - assert(ptrmap == NULL, "must be"); - } - } - - size_t max_non_null_offset() { - assert(COMPACTING, "must be"); - return _max_non_null_offset; } - inline bool do_bit(size_t offset); + bool do_bit(size_t offset); }; class DumpRegion { @@ -150,12 +127,17 @@ class DumpRegion { char* _base; char* _top; char* _end; + uintx _max_delta; bool _is_packed; ReservedSpace* _rs; VirtualSpace* _vs; + void commit_to(char* newtop); + public: - DumpRegion(const char* name) : _name(name), _base(NULL), _top(NULL), _end(NULL), _is_packed(false) {} + DumpRegion(const char* name, uintx max_delta = 0) + : _name(name), _base(NULL), _top(NULL), _end(NULL), + _max_delta(max_delta), _is_packed(false) {} char* expand_top_to(char* newtop); char* allocate(size_t num_bytes); diff --git a/src/hotspot/share/memory/archiveUtils.inline.hpp b/src/hotspot/share/memory/archiveUtils.inline.hpp index 7498635d874..5e65e9ba278 100644 --- a/src/hotspot/share/memory/archiveUtils.inline.hpp +++ b/src/hotspot/share/memory/archiveUtils.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * 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,32 +28,13 @@ #include "memory/archiveUtils.hpp" #include "utilities/bitMap.inline.hpp" -template -inline bool SharedDataRelocator::do_bit(size_t offset) { +inline bool SharedDataRelocator::do_bit(size_t offset) { address* p = _patch_base + offset; assert(_patch_base <= p && p < _patch_end, "must be"); address old_ptr = *p; - if (old_ptr == NULL) { - assert(COMPACTING, "NULL pointers should not be marked when relocating at run-time"); - } else { - assert(_valid_old_base <= old_ptr && old_ptr < _valid_old_end, "must be"); - } - - if (COMPACTING) { - // Start-up performance: use a template parameter to elide this block for run-time archive - // relocation. - assert(Arguments::is_dumping_archive(), "Don't do this during run-time archive loading!"); - if (old_ptr == NULL) { - _ptrmap->clear_bit(offset); - DEBUG_ONLY(log_trace(cds, reloc)("Clearing pointer [" PTR_FORMAT "] -> NULL @ " SIZE_FORMAT_W(9), p2i(p), offset)); - return true; - } else { - _max_non_null_offset = offset; - } - } else { - assert(old_ptr != NULL, "bits for NULL pointers should have been cleaned at dump time"); - } + assert(_valid_old_base <= old_ptr && old_ptr < _valid_old_end, "must be"); + assert(old_ptr != NULL, "bits for NULL pointers should have been cleaned at dump time"); address new_ptr = old_ptr + _delta; assert(new_ptr != NULL, "don't point to the bottom of the archive"); // See ArchivePtrMarker::mark_pointer(). diff --git a/src/hotspot/share/memory/arena.cpp b/src/hotspot/share/memory/arena.cpp index e7939d6f29e..8388f68c359 100644 --- a/src/hotspot/share/memory/arena.cpp +++ b/src/hotspot/share/memory/arena.cpp @@ -25,7 +25,6 @@ #include "precompiled.hpp" #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" -#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "runtime/os.hpp" #include "runtime/task.hpp" diff --git a/src/hotspot/share/memory/cppVtables.cpp b/src/hotspot/share/memory/cppVtables.cpp index b9f75c2c4ec..2d7d2a22dfe 100644 --- a/src/hotspot/share/memory/cppVtables.cpp +++ b/src/hotspot/share/memory/cppVtables.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "logging/log.hpp" #include "memory/archiveUtils.hpp" +#include "memory/archiveBuilder.hpp" #include "memory/cppVtables.hpp" #include "memory/metaspaceShared.hpp" #include "oops/flatArrayKlass.hpp" @@ -104,7 +105,7 @@ template CppVtableInfo* CppVtableCloner::allocate_and_initialize(const char* name) { int n = get_vtable_length(name); CppVtableInfo* info = - (CppVtableInfo*)MetaspaceShared::misc_code_dump_space()->allocate(CppVtableInfo::byte_size(n)); + (CppVtableInfo*)ArchiveBuilder::current()->mc_region()->allocate(CppVtableInfo::byte_size(n)); info->set_vtable_size(n); initialize(name, info); return info; @@ -218,7 +219,7 @@ CppVtableInfo** CppVtables::_index = NULL; char* CppVtables::dumptime_init() { assert(DumpSharedSpaces, "must"); size_t vtptrs_bytes = _num_cloned_vtable_kinds * sizeof(CppVtableInfo*); - _index = (CppVtableInfo**)MetaspaceShared::misc_code_dump_space()->allocate(vtptrs_bytes); + _index = (CppVtableInfo**)ArchiveBuilder::current()->mc_region()->allocate(vtptrs_bytes); CPP_VTABLE_TYPES_DO(ALLOCATE_AND_INITIALIZE_VTABLE); diff --git a/src/hotspot/share/memory/dumpAllocStats.cpp b/src/hotspot/share/memory/dumpAllocStats.cpp index 23264ca11bf..1628943f968 100644 --- a/src/hotspot/share/memory/dumpAllocStats.cpp +++ b/src/hotspot/share/memory/dumpAllocStats.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,25 +26,21 @@ #include "logging/log.hpp" #include "logging/logMessage.hpp" #include "memory/dumpAllocStats.hpp" -#include "memory/metaspaceShared.hpp" void DumpAllocStats::print_stats(int ro_all, int rw_all, int mc_all) { - // Calculate size of data that was not allocated by Metaspace::allocate() - MetaspaceSharedStats *stats = MetaspaceShared::stats(); - // symbols - _counts[RO][SymbolHashentryType] = stats->symbol.hashentry_count; - _bytes [RO][SymbolHashentryType] = stats->symbol.hashentry_bytes; + _counts[RO][SymbolHashentryType] = _symbol_stats.hashentry_count; + _bytes [RO][SymbolHashentryType] = _symbol_stats.hashentry_bytes; - _counts[RO][SymbolBucketType] = stats->symbol.bucket_count; - _bytes [RO][SymbolBucketType] = stats->symbol.bucket_bytes; + _counts[RO][SymbolBucketType] = _symbol_stats.bucket_count; + _bytes [RO][SymbolBucketType] = _symbol_stats.bucket_bytes; // strings - _counts[RO][StringHashentryType] = stats->string.hashentry_count; - _bytes [RO][StringHashentryType] = stats->string.hashentry_bytes; + _counts[RO][StringHashentryType] = _string_stats.hashentry_count; + _bytes [RO][StringHashentryType] = _string_stats.hashentry_bytes; - _counts[RO][StringBucketType] = stats->string.bucket_count; - _bytes [RO][StringBucketType] = stats->string.bucket_bytes; + _counts[RO][StringBucketType] = _string_stats.bucket_count; + _bytes [RO][StringBucketType] = _string_stats.bucket_bytes; // TODO: count things like dictionary, vtable, etc _bytes[RW][OtherType] += mc_all; @@ -70,7 +66,7 @@ void DumpAllocStats::print_stats(int ro_all, int rw_all, int mc_all) { LogMessage(cds) msg; - msg.debug("Detailed metadata info (excluding st regions; rw stats include mc regions):"); + msg.debug("Detailed metadata info (excluding heap regions; rw stats include mc regions):"); msg.debug("%s", hdr); msg.debug("%s", sep); for (int type = 0; type < int(_number_of_types); type ++) { diff --git a/src/hotspot/share/memory/dumpAllocStats.hpp b/src/hotspot/share/memory/dumpAllocStats.hpp index bb1e20b1191..fcffa2c07bb 100644 --- a/src/hotspot/share/memory/dumpAllocStats.hpp +++ b/src/hotspot/share/memory/dumpAllocStats.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ #define SHARE_MEMORY_DUMPALLOCSTATS_HPP #include "memory/allocation.hpp" +#include "classfile/compactHashtable.hpp" // This is for dumping detailed statistics for the allocations // in the shared spaces. @@ -57,17 +58,23 @@ class DumpAllocStats : public ResourceObj { } } -public: - enum { RO = 0, RW = 1 }; + CompactHashtableStats _symbol_stats; + CompactHashtableStats _string_stats; int _counts[2][_number_of_types]; int _bytes [2][_number_of_types]; +public: + enum { RO = 0, RW = 1 }; + DumpAllocStats() { memset(_counts, 0, sizeof(_counts)); memset(_bytes, 0, sizeof(_bytes)); }; + CompactHashtableStats* symbol_stats() { return &_symbol_stats; } + CompactHashtableStats* string_stats() { return &_string_stats; } + void record(MetaspaceObj::Type type, int byte_size, bool read_only) { assert(int(type) >= 0 && type < MetaspaceObj::_number_of_types, "sanity"); int which = (read_only) ? RO : RW; diff --git a/src/hotspot/share/memory/dynamicArchive.cpp b/src/hotspot/share/memory/dynamicArchive.cpp index 1c828f74faa..6d1bebfbb31 100644 --- a/src/hotspot/share/memory/dynamicArchive.cpp +++ b/src/hotspot/share/memory/dynamicArchive.cpp @@ -27,6 +27,7 @@ #include "classfile/classLoaderData.inline.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionaryShared.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/gcVMOperations.hpp" #include "gc/shared/gc_globals.hpp" #include "logging/log.hpp" @@ -37,7 +38,7 @@ #include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "oops/klass.inline.hpp" -#include "runtime/os.inline.hpp" +#include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/vmThread.hpp" #include "runtime/vmOperations.hpp" @@ -52,9 +53,6 @@ class DynamicArchiveBuilder : public ArchiveBuilder { return os::vm_allocation_granularity(); } - static const int _total_dump_regions = 3; - int _num_dump_regions_used; - public: void mark_pointer(address* ptr_loc) { ArchivePtrMarker::mark_pointer(ptr_loc); @@ -72,85 +70,29 @@ class DynamicArchiveBuilder : public ArchiveBuilder { return 0; } - if (!MetaspaceShared::is_in_shared_metaspace(a_name)) { - // a_name points to a Symbol in the top archive. - // When this method is called, a_name is still pointing to the output space. - // Translate it to point to the output space, so that it can be compared with - // Symbols in the base archive. - a_name = (Symbol*)(address(a_name) + _buffer_to_target_delta); - } - if (!MetaspaceShared::is_in_shared_metaspace(b_name)) { - b_name = (Symbol*)(address(b_name) + _buffer_to_target_delta); - } + u4 a_offset = ArchiveBuilder::current()->any_to_offset_u4(a_name); + u4 b_offset = ArchiveBuilder::current()->any_to_offset_u4(b_name); - return a_name->fast_compare(b_name); + if (a_offset < b_offset) { + return -1; + } else { + assert(a_offset > b_offset, "must be"); + return 1; + } } public: DynamicArchiveHeader *_header; - address _last_verified_top; - size_t _other_region_used_bytes; - // Conservative estimate for number of bytes needed for: - size_t _estimated_hashtable_bytes; // symbol table and dictionaries - size_t _estimated_trampoline_bytes; // method entry trampolines - - size_t estimate_archive_size(); - size_t estimate_class_file_size(); - address reserve_space_and_init_buffer_to_target_delta(); - void init_header(address addr); + void init_header(); void release_header(); void sort_methods(); void sort_methods(InstanceKlass* ik) const; void remark_pointers_for_instance_klass(InstanceKlass* k, bool should_mark) const; - void relocate_buffer_to_target(); void write_archive(char* serialized_data); - void init_first_dump_space(address reserved_bottom) { - DumpRegion* mc_space = MetaspaceShared::misc_code_dump_space(); - DumpRegion* rw_space = MetaspaceShared::read_write_dump_space(); - - // Use the same MC->RW->RO ordering as in the base archive. - MetaspaceShared::init_shared_dump_space(mc_space); - _current_dump_space = mc_space; - _last_verified_top = reserved_bottom; - _num_dump_regions_used = 1; - } - public: - DynamicArchiveBuilder() : ArchiveBuilder(MetaspaceShared::misc_code_dump_space(), - MetaspaceShared::read_write_dump_space(), - MetaspaceShared::read_only_dump_space()) { - _estimated_hashtable_bytes = 0; - _estimated_trampoline_bytes = 0; - - _num_dump_regions_used = 0; - } - - void start_dump_space(DumpRegion* next) { - address bottom = _last_verified_top; - address top = (address)(current_dump_space()->top()); - _other_region_used_bytes += size_t(top - bottom); - - MetaspaceShared::pack_dump_space(current_dump_space(), next, MetaspaceShared::shared_rs()); - _current_dump_space = next; - _num_dump_regions_used ++; - - _last_verified_top = (address)(current_dump_space()->top()); - } - - void verify_estimate_size(size_t estimate, const char* which) { - address bottom = _last_verified_top; - address top = (address)(current_dump_space()->top()); - size_t used = size_t(top - bottom) + _other_region_used_bytes; - int diff = int(estimate) - int(used); - - log_info(cds)("%s estimate = " SIZE_FORMAT " used = " SIZE_FORMAT "; diff = %d bytes", which, estimate, used, diff); - assert(diff >= 0, "Estimate is too small"); - - _last_verified_top = top; - _other_region_used_bytes = 0; - } + DynamicArchiveBuilder() : ArchiveBuilder() { } // Do this before and after the archive dump to see if any corruption // is caused by dynamic dumping. @@ -170,31 +112,19 @@ class DynamicArchiveBuilder : public ArchiveBuilder { DEBUG_ONLY(SystemDictionaryShared::NoClassLoadingMark nclm); SystemDictionaryShared::check_excluded_classes(); - gather_klasses_and_symbols(); - - // rw space starts ... - address reserved_bottom = reserve_space_and_init_buffer_to_target_delta(); - init_header(reserved_bottom); - - CHeapBitMap ptrmap; - ArchivePtrMarker::initialize(&ptrmap, (address*)reserved_bottom, (address*)current_dump_space()->top()); + init_header(); + gather_source_objs(); + reserve_buffer(); - allocate_method_trampolines(); + init_mc_region(); verify_estimate_size(_estimated_trampoline_bytes, "Trampolines"); - gather_source_objs(); - start_dump_space(MetaspaceShared::read_write_dump_space()); - log_info(cds, dynamic)("Copying %d klasses and %d symbols", klasses()->length(), symbols()->length()); - dump_rw_region(); - - // ro space starts ... - DumpRegion* ro_space = MetaspaceShared::read_only_dump_space(); - start_dump_space(ro_space); dump_ro_region(); - relocate_pointers(); + relocate_metaspaceobj_embedded_pointers(); + relocate_roots(); verify_estimate_size(_estimated_metaspaceobj_bytes, "MetaspaceObjs"); @@ -204,12 +134,14 @@ class DynamicArchiveBuilder : public ArchiveBuilder { // Note that these tables still point to the *original* objects, so // they would need to call DynamicArchive::original_to_target() to // get the correct addresses. - assert(current_dump_space() == ro_space, "Must be RO space"); + assert(current_dump_space() == ro_region(), "Must be RO space"); SymbolTable::write_to_archive(symbols()); + + ArchiveBuilder::OtherROAllocMark mark; SystemDictionaryShared::write_to_archive(false); - serialized_data = ro_space->top(); - WriteClosure wc(ro_space); + serialized_data = ro_region()->top(); + WriteClosure wc(ro_region()); SymbolTable::serialize_shared_table_header(&wc, false); SystemDictionaryShared::serialize_dictionary_headers(&wc, false); } @@ -225,8 +157,7 @@ class DynamicArchiveBuilder : public ArchiveBuilder { log_info(cds)("Adjust lambda proxy class dictionary"); SystemDictionaryShared::adjust_lambda_proxy_class_dictionary(); - log_info(cds)("Final relocation of pointers ... "); - relocate_buffer_to_target(); + relocate_to_requested(); write_archive(serialized_data); release_header(); @@ -236,76 +167,12 @@ class DynamicArchiveBuilder : public ArchiveBuilder { } virtual void iterate_roots(MetaspaceClosure* it, bool is_relocating_pointers) { - if (!is_relocating_pointers) { - SystemDictionaryShared::dumptime_classes_do(it); - } FileMapInfo::metaspace_pointers_do(it); + SystemDictionaryShared::dumptime_classes_do(it); } }; -size_t DynamicArchiveBuilder::estimate_archive_size() { - // size of the symbol table and two dictionaries, plus the RunTimeSharedClassInfo's - size_t symbol_table_est = SymbolTable::estimate_size_for_archive(); - size_t dictionary_est = SystemDictionaryShared::estimate_size_for_archive(); - _estimated_hashtable_bytes = symbol_table_est + dictionary_est; - - _estimated_trampoline_bytes = allocate_method_trampoline_info(); - - size_t total = 0; - - total += _estimated_metaspaceobj_bytes; - total += _estimated_hashtable_bytes; - total += _estimated_trampoline_bytes; - - // allow fragmentation at the end of each dump region - total += _total_dump_regions * reserve_alignment(); - - log_info(cds, dynamic)("_estimated_hashtable_bytes = " SIZE_FORMAT " + " SIZE_FORMAT " = " SIZE_FORMAT, - symbol_table_est, dictionary_est, _estimated_hashtable_bytes); - log_info(cds, dynamic)("_estimated_metaspaceobj_bytes = " SIZE_FORMAT, _estimated_metaspaceobj_bytes); - log_info(cds, dynamic)("_estimated_trampoline_bytes = " SIZE_FORMAT, _estimated_trampoline_bytes); - log_info(cds, dynamic)("total estimate bytes = " SIZE_FORMAT, total); - - return align_up(total, reserve_alignment()); -} - -address DynamicArchiveBuilder::reserve_space_and_init_buffer_to_target_delta() { - size_t total = estimate_archive_size(); - ReservedSpace rs(total); - if (!rs.is_reserved()) { - log_error(cds, dynamic)("Failed to reserve %d bytes of output buffer.", (int)total); - vm_direct_exit(0); - } - - address buffer_base = (address)rs.base(); - log_info(cds, dynamic)("Reserved output buffer space at : " PTR_FORMAT " [%d bytes]", - p2i(buffer_base), (int)total); - MetaspaceShared::set_shared_rs(rs); - - // At run time, we will mmap the dynamic archive at target_space_bottom. - // However, at dump time, we may not be able to write into the target_space, - // as it's occupied by dynamically loaded Klasses. So we allocate a buffer - // at an arbitrary location chosen by the OS. We will write all the dynamically - // archived classes into this buffer. At the final stage of dumping, we relocate - // all pointers that are inside the buffer_space to point to their (runtime) - // target location inside thetarget_space. - address target_space_bottom = - (address)align_up(MetaspaceShared::shared_metaspace_top(), reserve_alignment()); - _buffer_to_target_delta = intx(target_space_bottom) - intx(buffer_base); - - log_info(cds, dynamic)("Target archive space at : " PTR_FORMAT, p2i(target_space_bottom)); - log_info(cds, dynamic)("Buffer-space to target-space delta : " PTR_FORMAT, p2i((address)_buffer_to_target_delta)); - - return buffer_base; -} - -void DynamicArchiveBuilder::init_header(address reserved_bottom) { - _alloc_bottom = reserved_bottom; - _last_verified_top = reserved_bottom; - _other_region_used_bytes = 0; - - init_first_dump_space(reserved_bottom); - +void DynamicArchiveBuilder::init_header() { FileMapInfo* mapinfo = new FileMapInfo(false); assert(FileMapInfo::dynamic_info() == mapinfo, "must be"); _header = mapinfo->dynamic_header(); @@ -359,7 +226,8 @@ void DynamicArchiveBuilder::sort_methods(InstanceKlass* ik) const { if (log_is_enabled(Debug, cds, dynamic)) { ResourceMark rm; - log_debug(cds, dynamic)("sorting methods for " PTR_FORMAT " %s", p2i(to_target(ik)), ik->external_name()); + log_debug(cds, dynamic)("sorting methods for " PTR_FORMAT " (" PTR_FORMAT ") %s", + p2i(ik), p2i(to_requested(ik)), ik->external_name()); } // Method sorting may re-layout the [iv]tables, which would change the offset(s) @@ -427,126 +295,33 @@ void DynamicArchiveBuilder::remark_pointers_for_instance_klass(InstanceKlass* k, } } -class RelocateBufferToTarget: public BitMapClosure { - DynamicArchiveBuilder *_builder; - address* _buffer_bottom; - intx _buffer_to_target_delta; - public: - RelocateBufferToTarget(DynamicArchiveBuilder* builder, address* bottom, intx delta) : - _builder(builder), _buffer_bottom(bottom), _buffer_to_target_delta(delta) {} - - bool do_bit(size_t offset) { - address* p = _buffer_bottom + offset; - assert(_builder->is_in_buffer_space(p), "pointer must live in buffer space"); - - address old_ptr = *p; - if (_builder->is_in_buffer_space(old_ptr)) { - address new_ptr = old_ptr + _buffer_to_target_delta; - log_trace(cds, dynamic)("Final patch: @%6d [" PTR_FORMAT " -> " PTR_FORMAT "] " PTR_FORMAT " => " PTR_FORMAT, - (int)offset, p2i(p), p2i(_builder->to_target(p)), - p2i(old_ptr), p2i(new_ptr)); - *p = new_ptr; - } - - return true; // keep iterating - } -}; - -void DynamicArchiveBuilder::relocate_buffer_to_target() { - RelocateBufferToTarget patcher(this, (address*)_alloc_bottom, _buffer_to_target_delta); - ArchivePtrMarker::ptrmap()->iterate(&patcher); - +void DynamicArchiveBuilder::write_archive(char* serialized_data) { Array* table = FileMapInfo::saved_shared_path_table().table(); - SharedPathTable runtime_table(to_target(table), FileMapInfo::shared_path_table().size()); + SharedPathTable runtime_table(table, FileMapInfo::shared_path_table().size()); _header->set_shared_path_table(runtime_table); - - address relocatable_base = (address)SharedBaseAddress; - address relocatable_end = (address)(current_dump_space()->top()) + _buffer_to_target_delta; - - intx addr_delta = MetaspaceShared::final_delta(); - if (addr_delta == 0) { - ArchivePtrMarker::compact(relocatable_base, relocatable_end); - } else { - // The base archive is NOT mapped at MetaspaceShared::requested_base_address() (due to ASLR). - // This means that the current content of the dynamic archive is based on a random - // address. Let's relocate all the pointers, so that it can be mapped to - // MetaspaceShared::requested_base_address() without runtime relocation. - // - // Note: both the base and dynamic archive are written with - // FileMapHeader::_requested_base_address == MetaspaceShared::requested_base_address() - - // Patch all pointers that are marked by ptrmap within this region, - // where we have just dumped all the metaspace data. - address patch_base = (address)_alloc_bottom; - address patch_end = (address)current_dump_space()->top(); - - // the current value of the pointers to be patched must be within this - // range (i.e., must point to either the top archive (as currently mapped), or to the - // (targeted address of) the top archive) - address valid_old_base = relocatable_base; - address valid_old_end = relocatable_end; - size_t base_plus_top_size = valid_old_end - valid_old_base; - size_t top_size = patch_end - patch_base; - size_t base_size = base_plus_top_size - top_size; - assert(base_plus_top_size > base_size, "no overflow"); - assert(base_plus_top_size > top_size, "no overflow"); - - // after patching, the pointers must point inside this range - // (the requested location of the archive, as mapped at runtime). - address valid_new_base = (address)MetaspaceShared::requested_base_address(); - address valid_new_end = valid_new_base + base_plus_top_size; - - log_debug(cds)("Relocating archive from [" INTPTR_FORMAT " - " INTPTR_FORMAT "] to " - "[" INTPTR_FORMAT " - " INTPTR_FORMAT "], delta = " INTX_FORMAT " bytes", - p2i(patch_base + base_size), p2i(patch_end), - p2i(valid_new_base + base_size), p2i(valid_new_end), addr_delta); - - SharedDataRelocator patcher((address*)patch_base, (address*)patch_end, valid_old_base, valid_old_end, - valid_new_base, valid_new_end, addr_delta, ArchivePtrMarker::ptrmap()); - ArchivePtrMarker::ptrmap()->iterate(&patcher); - ArchivePtrMarker::compact(patcher.max_non_null_offset()); - } -} - -void DynamicArchiveBuilder::write_archive(char* serialized_data) { - int num_klasses = klasses()->length(); - int num_symbols = symbols()->length(); - - _header->set_serialized_data(to_target(serialized_data)); + _header->set_serialized_data(serialized_data); FileMapInfo* dynamic_info = FileMapInfo::dynamic_info(); assert(dynamic_info != NULL, "Sanity"); - // Now write the archived data including the file offsets. - const char* archive_name = Arguments::GetSharedDynamicArchivePath(); - dynamic_info->open_for_write(archive_name); - size_t bitmap_size_in_bytes; - char* bitmap = MetaspaceShared::write_core_archive_regions(dynamic_info, NULL, NULL, bitmap_size_in_bytes); - dynamic_info->set_final_requested_base((char*)MetaspaceShared::requested_base_address()); - dynamic_info->set_header_crc(dynamic_info->compute_header_crc()); - dynamic_info->write_header(); - dynamic_info->close(); - - write_cds_map_to_log(dynamic_info, NULL, NULL, - bitmap, bitmap_size_in_bytes); - FREE_C_HEAP_ARRAY(char, bitmap); - - address base = to_target(_alloc_bottom); - address top = address(current_dump_space()->top()) + _buffer_to_target_delta; + dynamic_info->open_for_write(Arguments::GetSharedDynamicArchivePath()); + ArchiveBuilder::write_archive(dynamic_info, NULL, NULL, NULL, NULL); + + address base = _requested_dynamic_archive_bottom; + address top = _requested_dynamic_archive_top; size_t file_size = pointer_delta(top, base, sizeof(char)); - base += MetaspaceShared::final_delta(); - top += MetaspaceShared::final_delta(); log_info(cds, dynamic)("Written dynamic archive " PTR_FORMAT " - " PTR_FORMAT " [" SIZE_FORMAT " bytes header, " SIZE_FORMAT " bytes total]", p2i(base), p2i(top), _header->header_size(), file_size); - log_info(cds, dynamic)("%d klasses; %d symbols", num_klasses, num_symbols); + + log_info(cds, dynamic)("%d klasses; %d symbols", klasses()->length(), symbols()->length()); } class VM_PopulateDynamicDumpSharedSpace: public VM_GC_Sync_Operation { - DynamicArchiveBuilder* _builder; + DynamicArchiveBuilder builder; public: - VM_PopulateDynamicDumpSharedSpace(DynamicArchiveBuilder* builder) : VM_GC_Sync_Operation(), _builder(builder) {} + VM_PopulateDynamicDumpSharedSpace() : VM_GC_Sync_Operation() {} VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; } void doit() { ResourceMark rm; @@ -560,7 +335,7 @@ class VM_PopulateDynamicDumpSharedSpace: public VM_GC_Sync_Operation { } FileMapInfo::check_nonempty_dir_in_shared_path_table(); - _builder->doit(); + builder.doit(); } }; @@ -571,62 +346,10 @@ void DynamicArchive::dump() { return; } - DynamicArchiveBuilder builder; - _builder = &builder; - VM_PopulateDynamicDumpSharedSpace op(&builder); + VM_PopulateDynamicDumpSharedSpace op; VMThread::execute(&op); - _builder = NULL; -} - -address DynamicArchive::original_to_buffer_impl(address orig_obj) { - assert(DynamicDumpSharedSpaces, "must be"); - address buff_obj = _builder->get_dumped_addr(orig_obj); - assert(buff_obj != NULL, "orig_obj must be used by the dynamic archive"); - assert(buff_obj != orig_obj, "call this only when you know orig_obj must be copied and not just referenced"); - assert(_builder->is_in_buffer_space(buff_obj), "must be"); - return buff_obj; } -address DynamicArchive::buffer_to_target_impl(address buff_obj) { - assert(DynamicDumpSharedSpaces, "must be"); - assert(_builder->is_in_buffer_space(buff_obj), "must be"); - return _builder->to_target(buff_obj); -} - -address DynamicArchive::original_to_target_impl(address orig_obj) { - assert(DynamicDumpSharedSpaces, "must be"); - if (MetaspaceShared::is_in_shared_metaspace(orig_obj)) { - // This happens when the top archive points to a Symbol* in the base archive. - return orig_obj; - } - address buff_obj = _builder->get_dumped_addr(orig_obj); - assert(buff_obj != NULL, "orig_obj must be used by the dynamic archive"); - if (buff_obj == orig_obj) { - // We are storing a pointer to an original object into the dynamic buffer. E.g., - // a Symbol* that used by both the base and top archives. - assert(MetaspaceShared::is_in_shared_metaspace(orig_obj), "must be"); - return orig_obj; - } else { - return _builder->to_target(buff_obj); - } -} - -uintx DynamicArchive::object_delta_uintx(void* buff_obj) { - assert(DynamicDumpSharedSpaces, "must be"); - address target_obj = _builder->to_target_no_check(address(buff_obj)); - assert(uintx(target_obj) >= SharedBaseAddress, "must be"); - return uintx(target_obj) - SharedBaseAddress; -} - -bool DynamicArchive::is_in_target_space(void *obj) { - assert(DynamicDumpSharedSpaces, "must be"); - return _builder->is_in_target_space(obj); -} - - -DynamicArchiveBuilder* DynamicArchive::_builder = NULL; - - bool DynamicArchive::validate(FileMapInfo* dynamic_info) { assert(!dynamic_info->is_static(), "must be"); // Check if the recorded base archive matches with the current one diff --git a/src/hotspot/share/memory/dynamicArchive.hpp b/src/hotspot/share/memory/dynamicArchive.hpp index fc24c300c33..7fa3000cc8b 100644 --- a/src/hotspot/share/memory/dynamicArchive.hpp +++ b/src/hotspot/share/memory/dynamicArchive.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,47 +58,8 @@ class DynamicArchiveHeader : public FileMapHeader { }; class DynamicArchive : AllStatic { - static class DynamicArchiveBuilder* _builder; - static address original_to_target_impl(address orig_obj); - static address original_to_buffer_impl(address orig_obj); - static address buffer_to_target_impl(address buff_obj); - public: static void dump(); - - // obj is a copy of a MetaspaceObj, stored in the dumping buffer. - // - // The return value is the runtime targeted location of this object as - // mapped from the dynamic archive. - template static T buffer_to_target(T buff_obj) { - return (T)buffer_to_target_impl(address(buff_obj)); - } - - // obj is an original MetaspaceObj used by the JVM (e.g., a valid Symbol* in the - // SymbolTable). - // - // The return value is the runtime targeted location of this object as - // mapped from the dynamic archive. - template static T original_to_target(T obj) { - return (T)original_to_target_impl(address(obj)); - } - - // obj is an original MetaspaceObj use by the JVM (e.g., a valid Symbol* in the - // SymbolTable). - // - // The return value is the location of this object in the dump time - // buffer space - template static T original_to_buffer(T obj) { - return (T)original_to_buffer_impl(address(obj)); - } - - // Delta of this object from SharedBaseAddress - static uintx object_delta_uintx(void* buff_obj); - - // Does obj point to an address inside the runtime target space of the dynamic - // archive? - static bool is_in_target_space(void *obj); - static bool is_mapped() { return FileMapInfo::dynamic_info() != NULL; } static bool validate(FileMapInfo* dynamic_info); }; diff --git a/src/hotspot/share/memory/filemap.cpp b/src/hotspot/share/memory/filemap.cpp index db4ce1208bb..944f719d9c3 100644 --- a/src/hotspot/share/memory/filemap.cpp +++ b/src/hotspot/share/memory/filemap.cpp @@ -36,6 +36,7 @@ #include "logging/log.hpp" #include "logging/logStream.hpp" #include "logging/logMessage.hpp" +#include "memory/archiveBuilder.hpp" #include "memory/archiveUtils.inline.hpp" #include "memory/dynamicArchive.hpp" #include "memory/filemap.hpp" @@ -303,7 +304,7 @@ void FileMapHeader::print(outputStream* st) { void SharedClassPathEntry::init_as_non_existent(const char* path, TRAPS) { _type = non_existent_entry; - set_name(path, THREAD); + set_name(path, CHECK); } void SharedClassPathEntry::init(bool is_modules_image, @@ -342,12 +343,12 @@ void SharedClassPathEntry::init(bool is_modules_image, // No need to save the name of the module file, as it will be computed at run time // to allow relocation of the JDK directory. const char* name = is_modules_image ? "" : cpe->name(); - set_name(name, THREAD); + set_name(name, CHECK); } void SharedClassPathEntry::set_name(const char* name, TRAPS) { size_t len = strlen(name) + 1; - _name = MetadataFactory::new_array(ClassLoaderData::the_null_class_loader_data(), (int)len, THREAD); + _name = MetadataFactory::new_array(ClassLoaderData::the_null_class_loader_data(), (int)len, CHECK); strcpy(_name->data(), name); } @@ -357,12 +358,12 @@ void SharedClassPathEntry::copy_from(SharedClassPathEntry* ent, ClassLoaderData* _timestamp = ent->_timestamp; _filesize = ent->_filesize; _from_class_path_attr = ent->_from_class_path_attr; - set_name(ent->name(), THREAD); + set_name(ent->name(), CHECK); if (ent->is_jar() && !ent->is_signed() && ent->manifest() != NULL) { Array* buf = MetadataFactory::new_array(loader_data, ent->manifest_size(), - THREAD); + CHECK); char* p = (char*)(buf->data()); memcpy(p, ent->manifest(), ent->manifest_size()); set_manifest(buf); @@ -448,7 +449,7 @@ void SharedPathTable::metaspace_pointers_do(MetaspaceClosure* it) { } } -void SharedPathTable::dumptime_init(ClassLoaderData* loader_data, Thread* THREAD) { +void SharedPathTable::dumptime_init(ClassLoaderData* loader_data, TRAPS) { size_t entry_size = sizeof(SharedClassPathEntry); int num_entries = 0; num_entries += ClassLoader::num_boot_classpath_entries(); @@ -457,7 +458,7 @@ void SharedPathTable::dumptime_init(ClassLoaderData* loader_data, Thread* THREAD num_entries += FileMapInfo::num_non_existent_class_paths(); size_t bytes = entry_size * num_entries; - _table = MetadataFactory::new_array(loader_data, (int)bytes, THREAD); + _table = MetadataFactory::new_array(loader_data, (int)bytes, CHECK); _size = num_entries; } @@ -465,44 +466,43 @@ void SharedPathTable::dumptime_init(ClassLoaderData* loader_data, Thread* THREAD // It is needed because some Java code continues to execute after dynamic dump has finished. // However, during dynamic dump, we have modified FileMapInfo::_shared_path_table so // FileMapInfo::shared_path(i) returns incorrect information in ClassLoader::record_result(). -void FileMapInfo::copy_shared_path_table(ClassLoaderData* loader_data, Thread* THREAD) { +void FileMapInfo::copy_shared_path_table(ClassLoaderData* loader_data, TRAPS) { size_t entry_size = sizeof(SharedClassPathEntry); size_t bytes = entry_size * _shared_path_table.size(); - _saved_shared_path_table = SharedPathTable(MetadataFactory::new_array(loader_data, (int)bytes, THREAD), - _shared_path_table.size()); + Array* array = MetadataFactory::new_array(loader_data, (int)bytes, CHECK); + _saved_shared_path_table = SharedPathTable(array, _shared_path_table.size()); for (int i = 0; i < _shared_path_table.size(); i++) { - _saved_shared_path_table.path_at(i)->copy_from(shared_path(i), loader_data, THREAD); + _saved_shared_path_table.path_at(i)->copy_from(shared_path(i), loader_data, CHECK); } } -void FileMapInfo::allocate_shared_path_table() { +void FileMapInfo::allocate_shared_path_table(TRAPS) { Arguments::assert_is_dumping_archive(); - EXCEPTION_MARK; // The following calls should never throw, but would exit VM on error. ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); ClassPathEntry* jrt = ClassLoader::get_jrt_entry(); assert(jrt != NULL, "No modular java runtime image present when allocating the CDS classpath entry table"); - _shared_path_table.dumptime_init(loader_data, THREAD); + _shared_path_table.dumptime_init(loader_data, CHECK); // 1. boot class path int i = 0; - i = add_shared_classpaths(i, "boot", jrt, THREAD); - i = add_shared_classpaths(i, "app", ClassLoader::app_classpath_entries(), THREAD); - i = add_shared_classpaths(i, "module", ClassLoader::module_path_entries(), THREAD); + i = add_shared_classpaths(i, "boot", jrt, CHECK); + i = add_shared_classpaths(i, "app", ClassLoader::app_classpath_entries(), CHECK); + i = add_shared_classpaths(i, "module", ClassLoader::module_path_entries(), CHECK); for (int x = 0; x < num_non_existent_class_paths(); x++, i++) { const char* path = _non_existent_class_paths->at(x); - shared_path(i)->init_as_non_existent(path, THREAD); + shared_path(i)->init_as_non_existent(path, CHECK); } assert(i == _shared_path_table.size(), "number of shared path entry mismatch"); - copy_shared_path_table(loader_data, THREAD); + copy_shared_path_table(loader_data, CHECK); } int FileMapInfo::add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS) { @@ -512,9 +512,9 @@ int FileMapInfo::add_shared_classpaths(int i, const char* which, ClassPathEntry const char* type = (is_jrt ? "jrt" : (cpe->is_jar_file() ? "jar" : "dir")); log_info(class, path)("add %s shared path (%s) %s", which, type, cpe->name()); SharedClassPathEntry* ent = shared_path(i); - ent->init(is_jrt, is_module_path, cpe, THREAD); + ent->init(is_jrt, is_module_path, cpe, CHECK_0); if (cpe->is_jar_file()) { - update_jar_manifest(cpe, ent, THREAD); + update_jar_manifest(cpe, ent, CHECK_0); } if (is_jrt) { cpe = ClassLoader::get_next_boot_classpath_entry(cpe); @@ -669,7 +669,7 @@ void FileMapInfo::update_jar_manifest(ClassPathEntry *cpe, SharedClassPathEntry* manifest = ClassLoaderExt::read_raw_manifest(cpe, &manifest_size, CHECK); Array* buf = MetadataFactory::new_array(loader_data, manifest_size, - THREAD); + CHECK); char* p = (char*)(buf->data()); memcpy(p, manifest, manifest_size); ent->set_manifest(buf); @@ -1255,25 +1255,11 @@ size_t FileMapRegion::used_aligned() const { return align_up(used(), os::vm_allocation_granularity()); } -void FileMapRegion::init(int region_index, char* base, size_t size, bool read_only, +void FileMapRegion::init(int region_index, size_t mapping_offset, size_t size, bool read_only, bool allow_exec, int crc) { _is_heap_region = HeapShared::is_heap_region(region_index); _is_bitmap_region = (region_index == MetaspaceShared::bm); - _mapping_offset = 0; - - if (_is_heap_region) { - assert(!DynamicDumpSharedSpaces, "must be"); - assert((base - (char*)CompressedKlassPointers::base()) % HeapWordSize == 0, "Sanity"); - if (base != NULL) { - _mapping_offset = (size_t)CompressedOops::encode_not_null((oop)base); - assert(_mapping_offset == (size_t)(uint32_t)_mapping_offset, "must be 32-bit only"); - } - } else { - if (base != NULL) { - assert(base >= (char*)SharedBaseAddress, "must be"); - _mapping_offset = base - (char*)SharedBaseAddress; - } - } + _mapping_offset = mapping_offset; _used = size; _read_only = read_only; _allow_exec = allow_exec; @@ -1314,29 +1300,35 @@ void FileMapInfo::write_region(int region, char* base, size_t size, Arguments::assert_is_dumping_archive(); FileMapRegion* si = space_at(region); - char* target_base; + char* requested_base; + size_t mapping_offset = 0; if (region == MetaspaceShared::bm) { - target_base = NULL; // always NULL for bm region. + requested_base = NULL; // always NULL for bm region + } else if (size == 0) { + // This is an unused region (e.g., a heap region when !INCLUDE_CDS_JAVA_HEAP) + requested_base = NULL; + } else if (HeapShared::is_heap_region(region)) { + assert(!DynamicDumpSharedSpaces, "must be"); + requested_base = base; + mapping_offset = (size_t)CompressedOops::encode_not_null((oop)base); + assert(mapping_offset == (size_t)(uint32_t)mapping_offset, "must be 32-bit only"); } else { - if (DynamicDumpSharedSpaces) { - assert(!HeapShared::is_heap_region(region), "dynamic archive doesn't support heap regions"); - target_base = DynamicArchive::buffer_to_target(base); - } else { - target_base = base; - } + char* requested_SharedBaseAddress = (char*)MetaspaceShared::requested_base_address(); + requested_base = ArchiveBuilder::current()->to_requested(base); + assert(requested_base >= requested_SharedBaseAddress, "must be"); + mapping_offset = requested_base - requested_SharedBaseAddress; } si->set_file_offset(_file_offset); - char* requested_base = (target_base == NULL) ? NULL : target_base + MetaspaceShared::final_delta(); int crc = ClassLoader::crc32(0, base, (jint)size); if (size > 0) { - log_debug(cds)("Shared file region (%-3s) %d: " SIZE_FORMAT_W(8) + log_info(cds)("Shared file region (%-3s) %d: " SIZE_FORMAT_W(8) " bytes, addr " INTPTR_FORMAT " file offset " SIZE_FORMAT_HEX_W(08) " crc 0x%08x", region_name(region), region, size, p2i(requested_base), _file_offset, crc); } - si->init(region, target_base, size, read_only, allow_exec, crc); + si->init(region, mapping_offset, size, read_only, allow_exec, crc); if (base != NULL) { write_bytes_aligned(base, size); @@ -1494,10 +1486,6 @@ void FileMapInfo::write_bytes_aligned(const void* buffer, size_t nbytes) { align_file_position(); } -void FileMapInfo::set_final_requested_base(char* b) { - header()->set_final_requested_base(b); -} - // Close the shared archive file. This does NOT unmap mapped regions. void FileMapInfo::close() { @@ -1575,7 +1563,7 @@ MapArchiveResult FileMapInfo::map_regions(int regions[], int num_regions, char* } header()->set_mapped_base_address(header()->requested_base_address() + addr_delta); - if (addr_delta != 0 && !relocate_pointers(addr_delta)) { + if (addr_delta != 0 && !relocate_pointers_in_core_regions(addr_delta)) { return MAP_ARCHIVE_OTHER_FAILURE; } @@ -1688,12 +1676,14 @@ char* FileMapInfo::map_bitmap_region() { return bitmap_base; } -bool FileMapInfo::relocate_pointers(intx addr_delta) { +// This is called when we cannot map the archive at the requested[ base address (usually 0x800000000). +// We relocate all pointers in the 3 core regions (mc, ro, rw). +bool FileMapInfo::relocate_pointers_in_core_regions(intx addr_delta) { log_debug(cds, reloc)("runtime archive relocation start"); char* bitmap_base = map_bitmap_region(); if (bitmap_base == NULL) { - return false; + return false; // OOM, or CRC check failure } else { size_t ptrmap_size_in_bits = header()->ptrmap_size_in_bits(); log_debug(cds, reloc)("mapped relocation bitmap @ " INTPTR_FORMAT " (" SIZE_FORMAT " bits)", @@ -1716,8 +1706,8 @@ bool FileMapInfo::relocate_pointers(intx addr_delta) { address valid_new_base = (address)header()->mapped_base_address(); address valid_new_end = (address)mapped_end(); - SharedDataRelocator patcher((address*)patch_base, (address*)patch_end, valid_old_base, valid_old_end, - valid_new_base, valid_new_end, addr_delta); + SharedDataRelocator patcher((address*)patch_base, (address*)patch_end, valid_old_base, valid_old_end, + valid_new_base, valid_new_end, addr_delta); ptrmap.iterate(&patcher); // The MetaspaceShared::bm region will be unmapped in MetaspaceShared::initialize_shared_spaces(). @@ -2191,6 +2181,10 @@ FileMapRegion* FileMapInfo::last_core_space() const { return space_at(MetaspaceShared::ro); } +void FileMapHeader::set_as_offset(char* p, size_t *offset) { + *offset = ArchiveBuilder::current()->any_to_offset((address)p); +} + int FileMapHeader::compute_crc() { char* start = (char*)this; // start computing from the field after _crc @@ -2369,7 +2363,8 @@ ClassFileStream* FileMapInfo::open_stream_for_jvmti(InstanceKlass* ik, Handle cl name->utf8_length()); ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader()); ClassFileStream* cfs = cpe->open_stream_for_loader(file_name, loader_data, THREAD); - assert(cfs != NULL, "must be able to read the classfile data of shared classes for built-in loaders."); + assert(!HAS_PENDING_EXCEPTION && + cfs != NULL, "must be able to read the classfile data of shared classes for built-in loaders."); log_debug(cds, jvmti)("classfile data for %s [%d: %s] = %d bytes", class_name, path_index, cfs->source(), cfs->length()); return cfs; diff --git a/src/hotspot/share/memory/filemap.hpp b/src/hotspot/share/memory/filemap.hpp index 37c41026fb3..de05861a5a1 100644 --- a/src/hotspot/share/memory/filemap.hpp +++ b/src/hotspot/share/memory/filemap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ #ifndef SHARE_MEMORY_FILEMAP_HPP #define SHARE_MEMORY_FILEMAP_HPP -#include "classfile/classLoader.hpp" #include "include/cds.h" #include "memory/metaspaceShared.hpp" #include "memory/metaspace.hpp" @@ -44,6 +43,9 @@ static const int JVM_IDENT_MAX = 256; class CHeapBitMap; +class ClassFileStream; +class ClassLoaderData; +class ClassPathEntry; class outputStream; class SharedClassPathEntry { @@ -117,7 +119,7 @@ class SharedPathTable { SharedPathTable() : _table(NULL), _size(0) {} SharedPathTable(Array* table, int size) : _table(table), _size(size) {} - void dumptime_init(ClassLoaderData* loader_data, Thread* THREAD); + void dumptime_init(ClassLoaderData* loader_data, TRAPS); void metaspace_pointers_do(MetaspaceClosure* it); int size() { @@ -169,7 +171,7 @@ class FileMapRegion: private CDSFileMapRegion { void set_read_only(bool v) { _read_only = v; } void set_mapped_base(char* p) { _mapped_base = p; } void set_mapped_from_file(bool v) { _mapped_from_file = v; } - void init(int region_index, char* base, size_t size, bool read_only, + void init(int region_index, size_t mapping_offset, size_t size, bool read_only, bool allow_exec, int crc); void init_oopmap(size_t oopmap_offset, size_t size_in_bits) { @@ -241,10 +243,7 @@ class FileMapHeader: private CDSFileMapHeaderBase { char* from_mapped_offset(size_t offset) const { return mapped_base_address() + offset; } - void set_mapped_offset(char* p, size_t *offset) { - assert(p >= mapped_base_address(), "sanity"); - *offset = p - mapped_base_address(); - } + void set_as_offset(char* p, size_t *offset); public: // Accessors -- fields declared in CDSFileMapHeaderBase unsigned int magic() const {return _magic;} @@ -287,8 +286,8 @@ class FileMapHeader: private CDSFileMapHeaderBase { narrowOop heap_obj_roots() const { return _heap_obj_roots; } void set_has_platform_or_app_classes(bool v) { _has_platform_or_app_classes = v; } - void set_cloned_vtables(char* p) { set_mapped_offset(p, &_cloned_vtables_offset); } - void set_serialized_data(char* p) { set_mapped_offset(p, &_serialized_data_offset); } + void set_cloned_vtables(char* p) { set_as_offset(p, &_cloned_vtables_offset); } + void set_serialized_data(char* p) { set_as_offset(p, &_serialized_data_offset); } void set_base_archive_name_size(size_t s) { _base_archive_name_size = s; } void set_base_archive_is_default(bool b) { _base_archive_is_default = b; } void set_header_size(size_t s) { _header_size = s; } @@ -296,15 +295,15 @@ class FileMapHeader: private CDSFileMapHeaderBase { void set_mapped_base_address(char* p) { _mapped_base_address = p; } void set_heap_obj_roots(narrowOop r) { _heap_obj_roots = r; } void set_i2i_entry_code_buffers(address p) { - set_mapped_offset((char*)p, &_i2i_entry_code_buffers_offset); + set_as_offset((char*)p, &_i2i_entry_code_buffers_offset); } void set_shared_path_table(SharedPathTable table) { - set_mapped_offset((char*)table.table(), &_shared_path_table_offset); + set_as_offset((char*)table.table(), &_shared_path_table_offset); _shared_path_table_size = table.size(); } - void set_final_requested_base(char* b) { + void set_requested_base(char* b) { _requested_base_address = b; _mapped_base_address = 0; } @@ -421,10 +420,9 @@ class FileMapInfo : public CHeapObj { bool is_mapped() const { return _is_mapped; } void set_is_mapped(bool v) { _is_mapped = v; } const char* full_path() const { return _full_path; } - void set_final_requested_base(char* b); - - char* requested_base_address() const { return header()->requested_base_address(); } + void set_requested_base(char* b) { header()->set_requested_base(b); } + char* requested_base_address() const { return header()->requested_base_address(); } class DynamicArchiveHeader* dynamic_header() const { assert(!is_static(), "must be"); @@ -502,8 +500,8 @@ class FileMapInfo : public CHeapObj { // Stop CDS sharing and unmap CDS regions. static void stop_sharing_and_unmap(const char* msg); - static void allocate_shared_path_table(); - static void copy_shared_path_table(ClassLoaderData* loader_data, Thread* THREAD); + static void allocate_shared_path_table(TRAPS); + static void copy_shared_path_table(ClassLoaderData* loader_data, TRAPS); static int add_shared_classpaths(int i, const char* which, ClassPathEntry *cpe, TRAPS); static void check_nonempty_dir_in_shared_path_table(); bool validate_shared_path_table(); @@ -578,7 +576,7 @@ class FileMapInfo : public CHeapObj { char* map_bitmap_region(); MapArchiveResult map_region(int i, intx addr_delta, char* mapped_base_address, ReservedSpace rs); bool read_region(int i, char* base, size_t size); - bool relocate_pointers(intx addr_delta); + bool relocate_pointers_in_core_regions(intx addr_delta); static size_t set_oopmaps_offset(GrowableArray *oopmaps, size_t curr_size); static size_t write_oopmaps(GrowableArray *oopmaps, size_t curr_offset, char* buffer); diff --git a/src/hotspot/share/memory/heap.cpp b/src/hotspot/share/memory/heap.cpp index d55bc07e2c0..fa9de515980 100644 --- a/src/hotspot/share/memory/heap.cpp +++ b/src/hotspot/share/memory/heap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ #include "memory/heap.hpp" #include "oops/oop.inline.hpp" #include "runtime/os.hpp" +#include "runtime/mutexLocker.hpp" #include "services/memTracker.hpp" #include "utilities/align.hpp" #include "utilities/powerOfTwo.hpp" @@ -206,17 +207,12 @@ bool CodeHeap::reserve(ReservedSpace rs, size_t committed_size, size_t segment_s _log2_segment_size = exact_log2(segment_size); // Reserve and initialize space for _memory. - size_t page_size = os::vm_page_size(); - if (os::can_execute_large_page_memory()) { - const size_t min_pages = 8; - page_size = MIN2(os::page_size_for_region_aligned(committed_size, min_pages), - os::page_size_for_region_aligned(rs.size(), min_pages)); - } - + const size_t page_size = ReservedSpace::actual_reserved_page_size(rs); const size_t granularity = os::vm_allocation_granularity(); const size_t c_size = align_up(committed_size, page_size); + assert(c_size <= rs.size(), "alignment made committed size to large"); - os::trace_page_sizes(_name, committed_size, rs.size(), page_size, + os::trace_page_sizes(_name, c_size, rs.size(), page_size, rs.base(), rs.size()); if (!_memory.initialize(rs, c_size)) { return false; diff --git a/src/hotspot/share/memory/heapShared.cpp b/src/hotspot/share/memory/heapShared.cpp index 8f513c169ad..e51d2c2e3e2 100644 --- a/src/hotspot/share/memory/heapShared.cpp +++ b/src/hotspot/share/memory/heapShared.cpp @@ -166,7 +166,7 @@ static void reset_states(oop obj, TRAPS) { void HeapShared::reset_archived_object_states(TRAPS) { assert(DumpSharedSpaces, "dump-time only"); log_debug(cds)("Resetting platform loader"); - reset_states(SystemDictionary::java_platform_loader(), THREAD); + reset_states(SystemDictionary::java_platform_loader(), CHECK); log_debug(cds)("Resetting system loader"); reset_states(SystemDictionary::java_system_loader(), THREAD); } @@ -247,7 +247,7 @@ void HeapShared::clear_root(int index) { } } -oop HeapShared::archive_heap_object(oop obj, Thread* THREAD) { +oop HeapShared::archive_heap_object(oop obj) { assert(DumpSharedSpaces, "dump-time only"); oop ao = find_archived_heap_object(obj); @@ -266,7 +266,6 @@ oop HeapShared::archive_heap_object(oop obj, Thread* THREAD) { oop archived_oop = (oop)G1CollectedHeap::heap()->archive_mem_allocate(len); if (archived_oop != NULL) { Copy::aligned_disjoint_words(cast_from_oop(obj), cast_from_oop(archived_oop), len); - MetaspaceShared::relocate_klass_ptr(archived_oop); // Reinitialize markword to remove age/marking/locking/etc. // // We need to retain the identity_hash, because it may have been used by some hashtables @@ -298,19 +297,19 @@ oop HeapShared::archive_heap_object(oop obj, Thread* THREAD) { return archived_oop; } -void HeapShared::archive_klass_objects(Thread* THREAD) { - GrowableArray* klasses = MetaspaceShared::collected_klasses(); +void HeapShared::archive_klass_objects() { + GrowableArray* klasses = ArchiveBuilder::current()->klasses(); assert(klasses != NULL, "sanity"); for (int i = 0; i < klasses->length(); i++) { - Klass* k = klasses->at(i); + Klass* k = ArchiveBuilder::get_relocated_klass(klasses->at(i)); // archive mirror object - java_lang_Class::archive_mirror(k, CHECK); + java_lang_Class::archive_mirror(k); // archive the resolved_referenes array if (k->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(k); - ik->constants()->archive_resolved_references(THREAD); + ik->constants()->archive_resolved_references(); } } } @@ -370,8 +369,7 @@ void HeapShared::copy_closed_archive_heap_objects( archive_object_subgraphs(closed_archive_subgraph_entry_fields, num_closed_archive_subgraph_entry_fields, true /* is_closed_archive */, - false /* is_full_module_graph */, - THREAD); + false /* is_full_module_graph */); G1CollectedHeap::heap()->end_archive_alloc_range(closed_archive, os::vm_allocation_granularity()); @@ -381,24 +379,21 @@ void HeapShared::copy_open_archive_heap_objects( GrowableArray * open_archive) { assert(is_heap_object_archiving_allowed(), "Cannot archive java heap objects"); - Thread* THREAD = Thread::current(); G1CollectedHeap::heap()->begin_archive_alloc_range(true /* open */); - java_lang_Class::archive_basic_type_mirrors(THREAD); + java_lang_Class::archive_basic_type_mirrors(); - archive_klass_objects(THREAD); + archive_klass_objects(); archive_object_subgraphs(open_archive_subgraph_entry_fields, num_open_archive_subgraph_entry_fields, false /* is_closed_archive */, - false /* is_full_module_graph */, - THREAD); + false /* is_full_module_graph */); if (MetaspaceShared::use_full_module_graph()) { archive_object_subgraphs(fmg_open_archive_subgraph_entry_fields, num_fmg_open_archive_subgraph_entry_fields, false /* is_closed_archive */, - true /* is_full_module_graph */, - THREAD); + true /* is_full_module_graph */); ClassLoaderDataShared::init_archived_oops(); } @@ -454,7 +449,7 @@ HeapShared::RunTimeKlassSubGraphInfoTable HeapShared::_run_time_subgraph_info_ KlassSubGraphInfo* HeapShared::init_subgraph_info(Klass* k, bool is_full_module_graph) { assert(DumpSharedSpaces, "dump time only"); bool created; - Klass* relocated_k = MetaspaceShared::get_relocated_klass(k); + Klass* relocated_k = ArchiveBuilder::get_relocated_klass(k); KlassSubGraphInfo* info = _dump_time_subgraph_info_table->put_if_absent(relocated_k, KlassSubGraphInfo(relocated_k, is_full_module_graph), &created); @@ -464,7 +459,7 @@ KlassSubGraphInfo* HeapShared::init_subgraph_info(Klass* k, bool is_full_module_ KlassSubGraphInfo* HeapShared::get_subgraph_info(Klass* k) { assert(DumpSharedSpaces, "dump time only"); - Klass* relocated_k = MetaspaceShared::get_relocated_klass(k); + Klass* relocated_k = ArchiveBuilder::get_relocated_klass(k); KlassSubGraphInfo* info = _dump_time_subgraph_info_table->get(relocated_k); assert(info != NULL, "must have been initialized"); return info; @@ -484,17 +479,16 @@ void KlassSubGraphInfo::add_subgraph_entry_field( // Add the Klass* for an object in the current KlassSubGraphInfo's subgraphs. // Only objects of boot classes can be included in sub-graph. -void KlassSubGraphInfo::add_subgraph_object_klass(Klass* orig_k, Klass* relocated_k) { +void KlassSubGraphInfo::add_subgraph_object_klass(Klass* orig_k) { assert(DumpSharedSpaces, "dump time only"); - assert(relocated_k == MetaspaceShared::get_relocated_klass(orig_k), - "must be the relocated Klass in the shared space"); + Klass* relocated_k = ArchiveBuilder::get_relocated_klass(orig_k); if (_subgraph_object_klasses == NULL) { _subgraph_object_klasses = new(ResourceObj::C_HEAP, mtClass) GrowableArray(50, mtClass); } - assert(ArchiveBuilder::singleton()->is_in_buffer_space(relocated_k), "must be a shared class"); + assert(ArchiveBuilder::current()->is_in_buffer_space(relocated_k), "must be a shared class"); if (_k == relocated_k) { // Don't add the Klass containing the sub-graph to it's own klass @@ -579,7 +573,7 @@ void ArchivedKlassSubGraphInfoRecord::init(KlassSubGraphInfo* info) { int num_entry_fields = entry_fields->length(); assert(num_entry_fields % 2 == 0, "sanity"); _entry_field_records = - MetaspaceShared::new_ro_array(num_entry_fields); + ArchiveBuilder::new_ro_array(num_entry_fields); for (int i = 0 ; i < num_entry_fields; i++) { _entry_field_records->at_put(i, entry_fields->at(i)); } @@ -590,7 +584,7 @@ void ArchivedKlassSubGraphInfoRecord::init(KlassSubGraphInfo* info) { if (subgraph_object_klasses != NULL) { int num_subgraphs_klasses = subgraph_object_klasses->length(); _subgraph_object_klasses = - MetaspaceShared::new_ro_array(num_subgraphs_klasses); + ArchiveBuilder::new_ro_array(num_subgraphs_klasses); for (int i = 0; i < num_subgraphs_klasses; i++) { Klass* subgraph_k = subgraph_object_klasses->at(i); if (log_is_enabled(Info, cds, heap)) { @@ -616,11 +610,11 @@ struct CopyKlassSubGraphInfoToArchive : StackObj { bool do_entry(Klass* klass, KlassSubGraphInfo& info) { if (info.subgraph_object_klasses() != NULL || info.subgraph_entry_fields() != NULL) { ArchivedKlassSubGraphInfoRecord* record = - (ArchivedKlassSubGraphInfoRecord*)MetaspaceShared::read_only_space_alloc(sizeof(ArchivedKlassSubGraphInfoRecord)); + (ArchivedKlassSubGraphInfoRecord*)ArchiveBuilder::ro_region_alloc(sizeof(ArchivedKlassSubGraphInfoRecord)); record->init(&info); - unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary(klass); - u4 delta = MetaspaceShared::object_delta_u4(record); + unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary((address)klass); + u4 delta = ArchiveBuilder::current()->any_to_offset_u4(record); _writer->add(hash, delta); } return true; // keep on iterating @@ -680,34 +674,35 @@ static void verify_the_heap(Klass* k, const char* which) { // Note: if a ArchivedKlassSubGraphInfoRecord contains non-early classes, and JVMTI // ClassFileLoadHook is enabled, it's possible for this class to be dynamically replaced. In // this case, we will not load the ArchivedKlassSubGraphInfoRecord and will clear its roots. -void HeapShared::resolve_classes(TRAPS) { +void HeapShared::resolve_classes(Thread* THREAD) { if (!is_mapped()) { return; // nothing to do } resolve_classes_for_subgraphs(closed_archive_subgraph_entry_fields, num_closed_archive_subgraph_entry_fields, - CHECK); + THREAD); resolve_classes_for_subgraphs(open_archive_subgraph_entry_fields, num_open_archive_subgraph_entry_fields, - CHECK); + THREAD); resolve_classes_for_subgraphs(fmg_open_archive_subgraph_entry_fields, num_fmg_open_archive_subgraph_entry_fields, - CHECK); + THREAD); } void HeapShared::resolve_classes_for_subgraphs(ArchivableStaticFieldInfo fields[], - int num, TRAPS) { + int num, Thread* THREAD) { for (int i = 0; i < num; i++) { ArchivableStaticFieldInfo* info = &fields[i]; TempNewSymbol klass_name = SymbolTable::new_symbol(info->klass_name); InstanceKlass* k = SystemDictionaryShared::find_builtin_class(klass_name); assert(k != NULL && k->is_shared_boot_class(), "sanity"); - resolve_classes_for_subgraph_of(k, CHECK); + resolve_classes_for_subgraph_of(k, THREAD); } } -void HeapShared::resolve_classes_for_subgraph_of(Klass* k, TRAPS) { - const ArchivedKlassSubGraphInfoRecord* record = resolve_or_init_classes_for_subgraph_of(k, /*do_init=*/false, THREAD); +void HeapShared::resolve_classes_for_subgraph_of(Klass* k, Thread* THREAD) { + const ArchivedKlassSubGraphInfoRecord* record = + resolve_or_init_classes_for_subgraph_of(k, /*do_init=*/false, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; } @@ -716,7 +711,7 @@ void HeapShared::resolve_classes_for_subgraph_of(Klass* k, TRAPS) { } } -void HeapShared::initialize_from_archived_subgraph(Klass* k, TRAPS) { +void HeapShared::initialize_from_archived_subgraph(Klass* k, Thread* THREAD) { if (!is_mapped()) { return; // nothing to do } @@ -733,7 +728,7 @@ void HeapShared::initialize_from_archived_subgraph(Klass* k, TRAPS) { } if (record != NULL) { - init_archived_fields_for(k, record, THREAD); + init_archived_fields_for(k, record); } } @@ -741,7 +736,10 @@ const ArchivedKlassSubGraphInfoRecord* HeapShared::resolve_or_init_classes_for_subgraph_of(Klass* k, bool do_init, TRAPS) { assert(!DumpSharedSpaces, "Should not be called with DumpSharedSpaces"); - unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary(k); + if (!k->is_shared()) { + return NULL; + } + unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary_quick(k); const ArchivedKlassSubGraphInfoRecord* record = _run_time_subgraph_info_table.lookup(k, hash, 0); // Initialize from archived data. Currently this is done only @@ -772,7 +770,11 @@ HeapShared::resolve_or_init_classes_for_subgraph_of(Klass* k, bool do_init, TRAP Array* klasses = record->subgraph_object_klasses(); if (klasses != NULL) { for (int i = 0; i < klasses->length(); i++) { - resolve_or_init(klasses->at(i), do_init, CHECK_NULL); + Klass* klass = klasses->at(i); + if (!klass->is_shared()) { + return NULL; + } + resolve_or_init(klass, do_init, CHECK_NULL); } } } @@ -798,7 +800,7 @@ void HeapShared::resolve_or_init(Klass* k, bool do_init, TRAPS) { } } -void HeapShared::init_archived_fields_for(Klass* k, const ArchivedKlassSubGraphInfoRecord* record, TRAPS) { +void HeapShared::init_archived_fields_for(Klass* k, const ArchivedKlassSubGraphInfoRecord* record) { verify_the_heap(k, "before"); // Load the subgraph entry fields from the record and store them back to @@ -829,7 +831,7 @@ void HeapShared::init_archived_fields_for(Klass* k, const ArchivedKlassSubGraphI } void HeapShared::clear_archived_roots_of(Klass* k) { - unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary(k); + unsigned int hash = SystemDictionaryShared::hash_for_shared_dictionary_quick(k); const ArchivedKlassSubGraphInfoRecord* record = _run_time_subgraph_info_table.lookup(k, hash, 0); if (record != NULL) { Array* entry_field_records = record->entry_field_records(); @@ -851,18 +853,16 @@ class WalkOopAndArchiveClosure: public BasicOopIterateClosure { KlassSubGraphInfo* _subgraph_info; oop _orig_referencing_obj; oop _archived_referencing_obj; - Thread* _thread; public: WalkOopAndArchiveClosure(int level, bool is_closed_archive, bool record_klasses_only, KlassSubGraphInfo* subgraph_info, - oop orig, oop archived, TRAPS) : + oop orig, oop archived) : _level(level), _is_closed_archive(is_closed_archive), _record_klasses_only(record_klasses_only), _subgraph_info(subgraph_info), - _orig_referencing_obj(orig), _archived_referencing_obj(archived), - _thread(THREAD) {} + _orig_referencing_obj(orig), _archived_referencing_obj(archived) {} void do_oop(narrowOop *p) { WalkOopAndArchiveClosure::do_oop_work(p); } void do_oop( oop *p) { WalkOopAndArchiveClosure::do_oop_work(p); } @@ -875,7 +875,6 @@ class WalkOopAndArchiveClosure: public BasicOopIterateClosure { size_t field_delta = pointer_delta(p, _orig_referencing_obj, sizeof(char)); T* new_p = (T*)(cast_from_oop
(_archived_referencing_obj) + field_delta); - Thread* THREAD = _thread; if (!_record_klasses_only && log_is_enabled(Debug, cds, heap)) { ResourceMark rm; @@ -888,7 +887,7 @@ class WalkOopAndArchiveClosure: public BasicOopIterateClosure { } oop archived = HeapShared::archive_reachable_objects_from( - _level + 1, _subgraph_info, obj, _is_closed_archive, THREAD); + _level + 1, _subgraph_info, obj, _is_closed_archive); assert(archived != NULL, "VM should have exited with unarchivable objects for _level > 1"); assert(HeapShared::is_archived_object(archived), "must be"); @@ -902,14 +901,13 @@ class WalkOopAndArchiveClosure: public BasicOopIterateClosure { } }; -void HeapShared::check_closed_archive_heap_region_object(InstanceKlass* k, - Thread* THREAD) { +void HeapShared::check_closed_archive_heap_region_object(InstanceKlass* k) { // Check fields in the object for (JavaFieldStream fs(k); !fs.done(); fs.next()) { if (!fs.access_flags().is_static()) { BasicType ft = fs.field_descriptor().field_type(); if (!fs.access_flags().is_final() && is_reference_type(ft)) { - ResourceMark rm(THREAD); + ResourceMark rm; log_warning(cds, heap)( "Please check reference field in %s instance in closed archive heap region: %s %s", k->external_name(), (fs.name())->as_C_string(), @@ -945,8 +943,7 @@ void HeapShared::check_module_oop(oop orig_module_obj) { oop HeapShared::archive_reachable_objects_from(int level, KlassSubGraphInfo* subgraph_info, oop orig_obj, - bool is_closed_archive, - TRAPS) { + bool is_closed_archive) { assert(orig_obj != NULL, "must be"); assert(!is_archived_object(orig_obj), "sanity"); @@ -986,7 +983,7 @@ oop HeapShared::archive_reachable_objects_from(int level, bool record_klasses_only = (archived_obj != NULL); if (archived_obj == NULL) { ++_num_new_archived_objs; - archived_obj = archive_heap_object(orig_obj, THREAD); + archived_obj = archive_heap_object(orig_obj); if (archived_obj == NULL) { // Skip archiving the sub-graph referenced from the current entry field. ResourceMark rm; @@ -1021,14 +1018,13 @@ oop HeapShared::archive_reachable_objects_from(int level, assert(archived_obj != NULL, "must be"); Klass *orig_k = orig_obj->klass(); - Klass *relocated_k = archived_obj->klass(); - subgraph_info->add_subgraph_object_klass(orig_k, relocated_k); + subgraph_info->add_subgraph_object_klass(orig_k); WalkOopAndArchiveClosure walker(level, is_closed_archive, record_klasses_only, - subgraph_info, orig_obj, archived_obj, THREAD); + subgraph_info, orig_obj, archived_obj); orig_obj->oop_iterate(&walker); if (is_closed_archive && orig_k->is_instance_klass()) { - check_closed_archive_heap_region_object(InstanceKlass::cast(orig_k), THREAD); + check_closed_archive_heap_region_object(InstanceKlass::cast(orig_k)); } return archived_obj; } @@ -1071,8 +1067,7 @@ void HeapShared::archive_reachable_objects_from_static_field(InstanceKlass *k, const char* klass_name, int field_offset, const char* field_name, - bool is_closed_archive, - TRAPS) { + bool is_closed_archive) { assert(DumpSharedSpaces, "dump time only"); assert(k->is_shared_boot_class(), "must be boot class"); @@ -1090,8 +1085,7 @@ void HeapShared::archive_reachable_objects_from_static_field(InstanceKlass *k, f->print_on(&out); } - oop af = archive_reachable_objects_from(1, subgraph_info, f, - is_closed_archive, CHECK); + oop af = archive_reachable_objects_from(1, subgraph_info, f, is_closed_archive); if (af == NULL) { log_error(cds, heap)("Archiving failed %s::%s (some reachable objects cannot be archived)", @@ -1304,8 +1298,7 @@ void HeapShared::init_for_dumping(Thread* THREAD) { void HeapShared::archive_object_subgraphs(ArchivableStaticFieldInfo fields[], int num, bool is_closed_archive, - bool is_full_module_graph, - Thread* THREAD) { + bool is_full_module_graph) { _num_total_subgraph_recordings = 0; _num_total_walked_objs = 0; _num_total_archived_objs = 0; @@ -1336,7 +1329,7 @@ void HeapShared::archive_object_subgraphs(ArchivableStaticFieldInfo fields[], archive_reachable_objects_from_static_field(f->klass, f->klass_name, f->offset, f->field_name, - is_closed_archive, CHECK); + is_closed_archive); } done_recording_subgraph(info->klass, klass_name); } @@ -1405,12 +1398,16 @@ ResourceBitMap HeapShared::calculate_oopmap(MemRegion region) { HeapWord* p = region.start(); HeapWord* end = region.end(); FindEmbeddedNonNullPointers finder((narrowOop*)p, &oopmap); + ArchiveBuilder* builder = DumpSharedSpaces ? ArchiveBuilder::current() : NULL; int num_objs = 0; while (p < end) { oop o = (oop)p; o->oop_iterate(&finder); p += o->size(); + if (DumpSharedSpaces) { + builder->relocate_klass_ptr(o); + } ++ num_objs; } diff --git a/src/hotspot/share/memory/heapShared.hpp b/src/hotspot/share/memory/heapShared.hpp index 429613c2af7..f3270cf6083 100644 --- a/src/hotspot/share/memory/heapShared.hpp +++ b/src/hotspot/share/memory/heapShared.hpp @@ -102,7 +102,7 @@ class KlassSubGraphInfo: public CHeapObj { } void add_subgraph_entry_field(int static_field_offset, oop v, bool is_closed_archive); - void add_subgraph_object_klass(Klass *orig_k, Klass *relocated_k); + void add_subgraph_object_klass(Klass *orig_k); int num_subgraph_object_klasses() { return _subgraph_object_klasses == NULL ? 0 : _subgraph_object_klasses->length(); @@ -200,21 +200,19 @@ class HeapShared: AllStatic { static DumpTimeKlassSubGraphInfoTable* _dump_time_subgraph_info_table; static RunTimeKlassSubGraphInfoTable _run_time_subgraph_info_table; - static void check_closed_archive_heap_region_object(InstanceKlass* k, - Thread* THREAD); + static void check_closed_archive_heap_region_object(InstanceKlass* k); static void archive_object_subgraphs(ArchivableStaticFieldInfo fields[], int num, bool is_closed_archive, - bool is_full_module_graph, - Thread* THREAD); + bool is_full_module_graph); // Archive object sub-graph starting from the given static field // in Klass k's mirror. static void archive_reachable_objects_from_static_field( InstanceKlass* k, const char* klass_name, int field_offset, const char* field_name, - bool is_closed_archive, TRAPS); + bool is_closed_archive); static void verify_subgraph_from_static_field( InstanceKlass* k, int field_offset) PRODUCT_RETURN; @@ -276,13 +274,13 @@ class HeapShared: AllStatic { static void copy_roots(); static void resolve_classes_for_subgraphs(ArchivableStaticFieldInfo fields[], - int num, TRAPS); - static void resolve_classes_for_subgraph_of(Klass* k, TRAPS); + int num, Thread* THREAD); + static void resolve_classes_for_subgraph_of(Klass* k, Thread* THREAD); static void clear_archived_roots_of(Klass* k); static const ArchivedKlassSubGraphInfoRecord* resolve_or_init_classes_for_subgraph_of(Klass* k, bool do_init, TRAPS); static void resolve_or_init(Klass* k, bool do_init, TRAPS); - static void init_archived_fields_for(Klass* k, const ArchivedKlassSubGraphInfoRecord* record, TRAPS); + static void init_archived_fields_for(Klass* k, const ArchivedKlassSubGraphInfoRecord* record); public: static void reset_archived_object_states(TRAPS); static void create_archived_object_cache() { @@ -298,9 +296,9 @@ class HeapShared: AllStatic { } static oop find_archived_heap_object(oop obj); - static oop archive_heap_object(oop obj, Thread* THREAD); + static oop archive_heap_object(oop obj); - static void archive_klass_objects(Thread* THREAD); + static void archive_klass_objects(); static void set_archive_heap_region_fixed() { _archive_heap_region_fixed = true; @@ -317,8 +315,7 @@ class HeapShared: AllStatic { static oop archive_reachable_objects_from(int level, KlassSubGraphInfo* subgraph_info, oop orig_obj, - bool is_closed_archive, - TRAPS); + bool is_closed_archive); static ResourceBitMap calculate_oopmap(MemRegion region); static void add_to_dumped_interned_strings(oop string); @@ -388,8 +385,8 @@ class HeapShared: AllStatic { inline static bool is_archived_object(oop p) NOT_CDS_JAVA_HEAP_RETURN_(false); - static void resolve_classes(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; - static void initialize_from_archived_subgraph(Klass* k, TRAPS) NOT_CDS_JAVA_HEAP_RETURN; + static void resolve_classes(Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN; + static void initialize_from_archived_subgraph(Klass* k, Thread* THREAD) NOT_CDS_JAVA_HEAP_RETURN; // NarrowOops stored in the CDS archive may use a different encoding scheme // than CompressedOops::{base,shift} -- see FileMapInfo::map_heap_regions_impl. diff --git a/src/hotspot/share/memory/metaspace.cpp b/src/hotspot/share/memory/metaspace.cpp index 9306a081781..4462b681680 100644 --- a/src/hotspot/share/memory/metaspace.cpp +++ b/src/hotspot/share/memory/metaspace.cpp @@ -672,23 +672,27 @@ void Metaspace::global_initialize() { metaspace::ChunkHeaderPool::initialize(); + if (DumpSharedSpaces) { + assert(!UseSharedSpaces, "sanity"); + MetaspaceShared::initialize_for_static_dump(); + } + // If UseCompressedClassPointers=1, we have two cases: - // a) if CDS is active (either dump time or runtime), it will create the ccs + // a) if CDS is active (runtime, Xshare=on), it will create the class space // for us, initialize it and set up CompressedKlassPointers encoding. // Class space will be reserved above the mapped archives. - // b) if CDS is not active, we will create the ccs on our own. It will be - // placed above the java heap, since we assume it has been placed in low + // b) if CDS either deactivated (Xshare=off) or a static dump is to be done (Xshare:dump), + // we will create the class space on our own. It will be placed above the java heap, + // since we assume it has been placed in low // address regions. We may rethink this (see JDK-8244943). Failing that, // it will be placed anywhere. #if INCLUDE_CDS // case (a) - if (DumpSharedSpaces) { - MetaspaceShared::initialize_dumptime_shared_and_meta_spaces(); - } else if (UseSharedSpaces) { + if (UseSharedSpaces) { + MetaspaceShared::initialize_runtime_shared_and_meta_spaces(); // If any of the archived space fails to map, UseSharedSpaces // is reset to false. - MetaspaceShared::initialize_runtime_shared_and_meta_spaces(); } if (DynamicDumpSharedSpaces && !UseSharedSpaces) { @@ -699,7 +703,7 @@ void Metaspace::global_initialize() { #ifdef _LP64 if (using_class_space() && !class_space_is_initialized()) { - assert(!UseSharedSpaces && !DumpSharedSpaces, "CDS should be off at this point"); + assert(!UseSharedSpaces, "CDS archive is not mapped at this point"); // case (b) ReservedSpace rs; diff --git a/src/hotspot/share/memory/metaspace/printMetaspaceInfoKlassClosure.cpp b/src/hotspot/share/memory/metaspace/printMetaspaceInfoKlassClosure.cpp index b100bf957c0..f852a5782ef 100644 --- a/src/hotspot/share/memory/metaspace/printMetaspaceInfoKlassClosure.cpp +++ b/src/hotspot/share/memory/metaspace/printMetaspaceInfoKlassClosure.cpp @@ -24,7 +24,6 @@ */ #include "precompiled.hpp" #include "memory/metaspace/printMetaspaceInfoKlassClosure.hpp" -#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "oops/klass.hpp" #include "oops/reflectionAccessorImplKlassHelper.hpp" diff --git a/src/hotspot/share/memory/metaspaceShared.cpp b/src/hotspot/share/memory/metaspaceShared.cpp index 3c4101b3c7d..08519e686c0 100644 --- a/src/hotspot/share/memory/metaspaceShared.cpp +++ b/src/hotspot/share/memory/metaspaceShared.cpp @@ -40,18 +40,15 @@ #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" #include "gc/shared/gcVMOperations.hpp" -#include "interpreter/abstractInterpreter.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/bytecodes.hpp" #include "logging/log.hpp" #include "logging/logMessage.hpp" #include "memory/archiveBuilder.hpp" -#include "memory/archiveUtils.inline.hpp" #include "memory/cppVtables.hpp" #include "memory/dumpAllocStats.hpp" -#include "memory/dynamicArchive.hpp" #include "memory/filemap.hpp" -#include "memory/heapShared.inline.hpp" +#include "memory/heapShared.hpp" #include "memory/metaspace.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/metaspaceShared.hpp" @@ -77,16 +74,12 @@ #include "utilities/bitMap.inline.hpp" #include "utilities/ostream.hpp" #include "utilities/defaultStream.hpp" -#include "utilities/hashtable.inline.hpp" #if INCLUDE_G1GC #include "gc/g1/g1CollectedHeap.inline.hpp" #endif -ReservedSpace MetaspaceShared::_shared_rs; -VirtualSpace MetaspaceShared::_shared_vs; ReservedSpace MetaspaceShared::_symbol_rs; VirtualSpace MetaspaceShared::_symbol_vs; -MetaspaceSharedStats MetaspaceShared::_stats; bool MetaspaceShared::_has_error_classes; bool MetaspaceShared::_archive_loading_failed = false; bool MetaspaceShared::_remapped_readwrite = false; @@ -107,63 +100,30 @@ bool MetaspaceShared::_use_full_module_graph = true; // oa0 - open archive heap space #0 // oa1 - open archive heap space #1 (may be empty) // -// The mc, rw, and ro regions are linearly allocated, starting from -// SharedBaseAddress, in the order of mc->rw->ro. The size of these 3 regions -// are page-aligned, and there's no gap between any consecutive regions. +// bm - bitmap for relocating the above 7 regions. +// +// The mc, rw, and ro regions are linearly allocated, in the order of mc->rw->ro. +// These regions are aligned with MetaspaceShared::reserved_space_alignment(). // // These 3 regions are populated in the following steps: -// [1] All classes are loaded in MetaspaceShared::preload_classes(). All metadata are -// temporarily allocated outside of the shared regions. Only the method entry -// trampolines are written into the mc region. -// [2] C++ vtables are copied into the mc region. +// [0] All classes are loaded in MetaspaceShared::preload_classes(). All metadata are +// temporarily allocated outside of the shared regions. +// [1] We enter a safepoint and allocate a buffer for the mc/rw/ro regions. +// [2] C++ vtables and method trampolines are copied into the mc region. // [3] ArchiveBuilder copies RW metadata into the rw region. // [4] ArchiveBuilder copies RO metadata into the ro region. // [5] SymbolTable, StringTable, SystemDictionary, and a few other read-only data // are copied into the ro region as read-only tables. // -// The s0/s1 and oa0/oa1 regions are populated inside HeapShared::archive_java_heap_objects. -// Their layout is independent of the other 4 regions. - -static DumpRegion _mc_region("mc"), _ro_region("ro"), _rw_region("rw"), _symbol_region("symbols"); -static size_t _total_closed_archive_region_size = 0, _total_open_archive_region_size = 0; - -void MetaspaceShared::init_shared_dump_space(DumpRegion* first_space) { - first_space->init(&_shared_rs, &_shared_vs); -} +// The ca0/ca1 and oa0/oa1 regions are populated inside HeapShared::archive_java_heap_objects. +// Their layout is independent of the mc/rw/ro regions. -DumpRegion* MetaspaceShared::misc_code_dump_space() { - return &_mc_region; -} - -DumpRegion* MetaspaceShared::read_write_dump_space() { - return &_rw_region; -} - -DumpRegion* MetaspaceShared::read_only_dump_space() { - return &_ro_region; -} - -void MetaspaceShared::pack_dump_space(DumpRegion* current, DumpRegion* next, - ReservedSpace* rs) { - current->pack(next); -} +static DumpRegion _symbol_region("symbols"); char* MetaspaceShared::symbol_space_alloc(size_t num_bytes) { return _symbol_region.allocate(num_bytes); } -char* MetaspaceShared::misc_code_space_alloc(size_t num_bytes) { - return _mc_region.allocate(num_bytes); -} - -char* MetaspaceShared::read_only_space_alloc(size_t num_bytes) { - return _ro_region.allocate(num_bytes); -} - -char* MetaspaceShared::read_write_space_alloc(size_t num_bytes) { - return _rw_region.allocate(num_bytes); -} - size_t MetaspaceShared::reserved_space_alignment() { return os::vm_allocation_granularity(); } static bool shared_base_valid(char* shared_base) { @@ -174,13 +134,13 @@ static bool shared_base_valid(char* shared_base) { #endif } -static bool shared_base_too_high(char* shared_base, size_t cds_total) { - if (SharedBaseAddress != 0 && shared_base < (char*)SharedBaseAddress) { +static bool shared_base_too_high(char* specified_base, char* aligned_base, size_t cds_max) { + if (specified_base != NULL && aligned_base < specified_base) { // SharedBaseAddress is very high (e.g., 0xffffffffffffff00) so // align_up(SharedBaseAddress, MetaspaceShared::reserved_space_alignment()) has wrapped around. return true; } - if (max_uintx - uintx(shared_base) < uintx(cds_total)) { + if (max_uintx - uintx(aligned_base) < uintx(cds_max)) { // The end of the archive will wrap around return true; } @@ -188,164 +148,51 @@ static bool shared_base_too_high(char* shared_base, size_t cds_total) { return false; } -static char* compute_shared_base(size_t cds_total) { - char* shared_base = (char*)align_up((char*)SharedBaseAddress, MetaspaceShared::reserved_space_alignment()); +static char* compute_shared_base(size_t cds_max) { + char* specified_base = (char*)SharedBaseAddress; + char* aligned_base = align_up(specified_base, MetaspaceShared::reserved_space_alignment()); + const char* err = NULL; - if (shared_base_too_high(shared_base, cds_total)) { + if (shared_base_too_high(specified_base, aligned_base, cds_max)) { err = "too high"; - } else if (!shared_base_valid(shared_base)) { + } else if (!shared_base_valid(aligned_base)) { err = "invalid for this platform"; + } else { + return aligned_base; } - if (err) { - log_warning(cds)("SharedBaseAddress (" INTPTR_FORMAT ") is %s. Reverted to " INTPTR_FORMAT, - p2i((void*)SharedBaseAddress), err, - p2i((void*)Arguments::default_SharedBaseAddress())); - SharedBaseAddress = Arguments::default_SharedBaseAddress(); - shared_base = (char*)align_up((char*)SharedBaseAddress, MetaspaceShared::reserved_space_alignment()); - } - assert(!shared_base_too_high(shared_base, cds_total) && shared_base_valid(shared_base), "Sanity"); - return shared_base; + + log_warning(cds)("SharedBaseAddress (" INTPTR_FORMAT ") is %s. Reverted to " INTPTR_FORMAT, + p2i((void*)SharedBaseAddress), err, + p2i((void*)Arguments::default_SharedBaseAddress())); + + specified_base = (char*)Arguments::default_SharedBaseAddress(); + aligned_base = align_up(specified_base, MetaspaceShared::reserved_space_alignment()); + + // Make sure the default value of SharedBaseAddress specified in globals.hpp is sane. + assert(!shared_base_too_high(specified_base, aligned_base, cds_max), "Sanity"); + assert(shared_base_valid(aligned_base), "Sanity"); + return aligned_base; } -void MetaspaceShared::initialize_dumptime_shared_and_meta_spaces() { +void MetaspaceShared::initialize_for_static_dump() { assert(DumpSharedSpaces, "should be called for dump time only"); + // The max allowed size for CDS archive. We use this to limit SharedBaseAddress + // to avoid address space wrap around. + size_t cds_max; const size_t reserve_alignment = MetaspaceShared::reserved_space_alignment(); #ifdef _LP64 - // On 64-bit VM we reserve a 4G range and, if UseCompressedClassPointers=1, - // will use that to house both the archives and the ccs. See below for - // details. const uint64_t UnscaledClassSpaceMax = (uint64_t(max_juint) + 1); - const size_t cds_total = align_down(UnscaledClassSpaceMax, reserve_alignment); + cds_max = align_down(UnscaledClassSpaceMax, reserve_alignment); #else // We don't support archives larger than 256MB on 32-bit due to limited // virtual address space. - size_t cds_total = align_down(256*M, reserve_alignment); + cds_max = align_down(256*M, reserve_alignment); #endif - char* shared_base = compute_shared_base(cds_total); - _requested_base_address = shared_base; - - // Whether to use SharedBaseAddress as attach address. - bool use_requested_base = true; - - if (shared_base == NULL) { - use_requested_base = false; - } - - if (ArchiveRelocationMode == 1) { - log_info(cds)("ArchiveRelocationMode == 1: always allocate class space at an alternative address"); - use_requested_base = false; - } - - // First try to reserve the space at the specified SharedBaseAddress. - assert(!_shared_rs.is_reserved(), "must be"); - if (use_requested_base) { - _shared_rs = ReservedSpace(cds_total, reserve_alignment, - false /* large */, (char*)shared_base); - if (_shared_rs.is_reserved()) { - assert(_shared_rs.base() == shared_base, "should match"); - } else { - log_info(cds)("dumptime space reservation: failed to map at " - "SharedBaseAddress " PTR_FORMAT, p2i(shared_base)); - } - } - if (!_shared_rs.is_reserved()) { - // Get a reserved space anywhere if attaching at the SharedBaseAddress - // fails: - if (UseCompressedClassPointers) { - // If we need to reserve class space as well, let the platform handle - // the reservation. - LP64_ONLY(_shared_rs = - Metaspace::reserve_address_space_for_compressed_classes(cds_total);) - NOT_LP64(ShouldNotReachHere();) - } else { - // anywhere is fine. - _shared_rs = ReservedSpace(cds_total, reserve_alignment, - false /* large */, (char*)NULL); - } - } - - if (!_shared_rs.is_reserved()) { - vm_exit_during_initialization("Unable to reserve memory for shared space", - err_msg(SIZE_FORMAT " bytes.", cds_total)); - } - -#ifdef _LP64 - - if (UseCompressedClassPointers) { - - assert(CompressedKlassPointers::is_valid_base((address)_shared_rs.base()), "Sanity"); - - // On 64-bit VM, if UseCompressedClassPointers=1, the compressed class space - // must be allocated near the cds such as that the compressed Klass pointer - // encoding can be used to en/decode pointers from both cds and ccs. Since - // Metaspace cannot do this (it knows nothing about cds), we do it for - // Metaspace here and pass it the space to use for ccs. - // - // We do this by reserving space for the ccs behind the archives. Note - // however that ccs follows a different alignment - // (Metaspace::reserve_alignment), so there may be a gap between ccs and - // cds. - // We use a similar layout at runtime, see reserve_address_space_for_archives(). - // - // +-- SharedBaseAddress (default = 0x800000000) - // v - // +-..---------+---------+ ... +----+----+----+--------+-----------------+ - // | Heap | Archive | | MC | RW | RO | [gap] | class space | - // +-..---------+---------+ ... +----+----+----+--------+-----------------+ - // |<-- MaxHeapSize -->| |<-- UnscaledClassSpaceMax = 4GB -->| - // - // Note: ccs must follow the archives, and the archives must start at the - // encoding base. However, the exact placement of ccs does not matter as - // long as it it resides in the encoding range of CompressedKlassPointers - // and comes after the archive. - // - // We do this by splitting up the allocated 4G into 3G of archive space, - // followed by 1G for the ccs: - // + The upper 1 GB is used as the "temporary compressed class space" - // -- preload_classes() will store Klasses into this space. - // + The lower 3 GB is used for the archive -- when preload_classes() - // is done, ArchiveBuilder will copy the class metadata into this - // space, first the RW parts, then the RO parts. - - // Starting address of ccs must be aligned to Metaspace::reserve_alignment()... - size_t class_space_size = align_down(_shared_rs.size() / 4, Metaspace::reserve_alignment()); - address class_space_start = (address)align_down(_shared_rs.end() - class_space_size, Metaspace::reserve_alignment()); - size_t archive_size = class_space_start - (address)_shared_rs.base(); - - ReservedSpace tmp_class_space = _shared_rs.last_part(archive_size); - _shared_rs = _shared_rs.first_part(archive_size); - - // ... as does the size of ccs. - tmp_class_space = tmp_class_space.first_part(class_space_size); - CompressedClassSpaceSize = class_space_size; - - // Let Metaspace initialize ccs - Metaspace::initialize_class_space(tmp_class_space); - - // and set up CompressedKlassPointers encoding. - CompressedKlassPointers::initialize((address)_shared_rs.base(), cds_total); - - log_info(cds)("narrow_klass_base = " PTR_FORMAT ", narrow_klass_shift = %d", - p2i(CompressedKlassPointers::base()), CompressedKlassPointers::shift()); - - log_info(cds)("Allocated temporary class space: " SIZE_FORMAT " bytes at " PTR_FORMAT, - CompressedClassSpaceSize, p2i(tmp_class_space.base())); - - assert(_shared_rs.end() == tmp_class_space.base() && - is_aligned(_shared_rs.base(), MetaspaceShared::reserved_space_alignment()) && - is_aligned(tmp_class_space.base(), Metaspace::reserve_alignment()) && - is_aligned(tmp_class_space.size(), Metaspace::reserve_alignment()), "Sanity"); - } - -#endif - - init_shared_dump_space(&_mc_region); - SharedBaseAddress = (size_t)_shared_rs.base(); - log_info(cds)("Allocated shared space: " SIZE_FORMAT " bytes at " PTR_FORMAT, - _shared_rs.size(), p2i(_shared_rs.base())); + _requested_base_address = compute_shared_base(cds_max); + SharedBaseAddress = (size_t)_requested_base_address; size_t symbol_rs_size = LP64_ONLY(3 * G) NOT_LP64(128 * M); _symbol_rs = ReservedSpace(symbol_rs_size); @@ -431,43 +278,6 @@ void MetaspaceShared::read_extra_data(const char* filename, TRAPS) { } } -void MetaspaceShared::commit_to(ReservedSpace* rs, VirtualSpace* vs, char* newtop) { - Arguments::assert_is_dumping_archive(); - char* base = rs->base(); - size_t need_committed_size = newtop - base; - size_t has_committed_size = vs->committed_size(); - if (need_committed_size < has_committed_size) { - return; - } - - size_t min_bytes = need_committed_size - has_committed_size; - size_t preferred_bytes = 1 * M; - size_t uncommitted = vs->reserved_size() - has_committed_size; - - size_t commit =MAX2(min_bytes, preferred_bytes); - commit = MIN2(commit, uncommitted); - assert(commit <= uncommitted, "sanity"); - - bool result = vs->expand_by(commit, false); - if (rs == &_shared_rs) { - ArchivePtrMarker::expand_ptr_end((address*)vs->high()); - } - - if (!result) { - vm_exit_during_initialization(err_msg("Failed to expand shared space to " SIZE_FORMAT " bytes", - need_committed_size)); - } - - assert(rs == &_shared_rs || rs == &_symbol_rs, "must be"); - const char* which = (rs == &_shared_rs) ? "shared" : "symbol"; - log_debug(cds)("Expanding %s spaces by " SIZE_FORMAT_W(7) " bytes [total " SIZE_FORMAT_W(9) " bytes ending at %p]", - which, commit, vs->actual_committed_size(), vs->high()); -} - -void MetaspaceShared::initialize_ptr_marker(CHeapBitMap* ptrmap) { - ArchivePtrMarker::initialize(ptrmap, (address*)_shared_vs.low(), (address*)_shared_vs.high()); -} - // Read/write a data stream for restoring/preserving metadata pointers and // miscellaneous data from/to the shared archive file. @@ -514,14 +324,10 @@ void MetaspaceShared::serialize(SerializeClosure* soc) { soc->do_tag(666); } -void MetaspaceShared::init_misc_code_space() { - // We don't want any valid object to be at the very bottom of the archive. - // See ArchivePtrMarker::mark_pointer(). - MetaspaceShared::misc_code_space_alloc(16); - - size_t trampoline_size = SharedRuntime::trampoline_size(); - size_t buf_size = (size_t)AbstractInterpreter::number_of_method_entries * trampoline_size; - _i2i_entry_code_buffers = (address)misc_code_space_alloc(buf_size); +void MetaspaceShared::set_i2i_entry_code_buffers(address b) { + assert(DumpSharedSpaces, "must be"); + assert(_i2i_entry_code_buffers == NULL, "initialize only once"); + _i2i_entry_code_buffers = b; } address MetaspaceShared::i2i_entry_code_buffers() { @@ -530,26 +336,6 @@ address MetaspaceShared::i2i_entry_code_buffers() { return _i2i_entry_code_buffers; } -uintx MetaspaceShared::object_delta_uintx(void* obj) { - Arguments::assert_is_dumping_archive(); - if (DumpSharedSpaces) { - assert(shared_rs()->contains(obj), "must be"); - } else { - assert(is_in_shared_metaspace(obj) || DynamicArchive::is_in_target_space(obj), "must be"); - } - address base_address = address(SharedBaseAddress); - uintx deltax = address(obj) - base_address; - return deltax; -} - -// Global object for holding classes that have been loaded. Since this -// is run at a safepoint just before exit, this is the entire set of classes. -static GrowableArray* _global_klass_objects; - -GrowableArray* MetaspaceShared::collected_klasses() { - return _global_klass_objects; -} - static void rewrite_nofast_bytecode(const methodHandle& method) { BytecodeStream bcs(method); while (!bcs.is_last_bytecode()) { @@ -590,7 +376,7 @@ class VM_PopulateDumpSharedSpace : public VM_GC_Operation { GrowableArray *_closed_archive_heap_oopmaps; GrowableArray *_open_archive_heap_oopmaps; - void dump_java_heap_objects() NOT_CDS_JAVA_HEAP_RETURN; + void dump_java_heap_objects(GrowableArray* klasses) NOT_CDS_JAVA_HEAP_RETURN; void dump_archive_heap_oopmaps() NOT_CDS_JAVA_HEAP_RETURN; void dump_archive_heap_oopmaps(GrowableArray* regions, GrowableArray* oopmaps); @@ -599,11 +385,6 @@ class VM_PopulateDumpSharedSpace : public VM_GC_Operation { SymbolTable::write_to_archive(symbols); } char* dump_read_only_tables(); - void print_region_stats(FileMapInfo* map_info); - void print_bitmap_region_stats(size_t size, size_t total_size); - void print_heap_region_stats(GrowableArray *heap_mem, - const char *name, size_t total_size); - void relocate_to_requested_base_address(CHeapBitMap* ptrmap); public: @@ -620,11 +401,7 @@ class VM_PopulateDumpSharedSpace : public VM_GC_Operation { class StaticArchiveBuilder : public ArchiveBuilder { public: - StaticArchiveBuilder(DumpRegion* mc_region, DumpRegion* rw_region, DumpRegion* ro_region) - : ArchiveBuilder(mc_region, rw_region, ro_region) { - _alloc_bottom = address(SharedBaseAddress); - _buffer_to_target_delta = 0; - } + StaticArchiveBuilder() : ArchiveBuilder() {} virtual void iterate_roots(MetaspaceClosure* it, bool is_relocating_pointers) { FileMapInfo::metaspace_pointers_do(it, false); @@ -651,8 +428,9 @@ char* VM_PopulateDumpSharedSpace::dump_read_only_tables() { SystemDictionaryShared::write_to_archive(); // Write the other data to the output array. - char* start = _ro_region.top(); - WriteClosure wc(&_ro_region); + DumpRegion* ro_region = ArchiveBuilder::current()->ro_region(); + char* start = ro_region->top(); + WriteClosure wc(ro_region); MetaspaceShared::serialize(&wc); // Write the bitmaps for patching the archive heap regions @@ -663,50 +441,8 @@ char* VM_PopulateDumpSharedSpace::dump_read_only_tables() { return start; } -void VM_PopulateDumpSharedSpace::relocate_to_requested_base_address(CHeapBitMap* ptrmap) { - intx addr_delta = MetaspaceShared::final_delta(); - if (addr_delta == 0) { - ArchivePtrMarker::compact((address)SharedBaseAddress, (address)_ro_region.top()); - } else { - // We are not able to reserve space at MetaspaceShared::requested_base_address() (due to ASLR). - // This means that the current content of the archive is based on a random - // address. Let's relocate all the pointers, so that it can be mapped to - // MetaspaceShared::requested_base_address() without runtime relocation. - // - // Note: both the base and dynamic archive are written with - // FileMapHeader::_requested_base_address == MetaspaceShared::requested_base_address() - - // Patch all pointers that are marked by ptrmap within this region, - // where we have just dumped all the metaspace data. - address patch_base = (address)SharedBaseAddress; - address patch_end = (address)_ro_region.top(); - size_t size = patch_end - patch_base; - - // the current value of the pointers to be patched must be within this - // range (i.e., must point to valid metaspace objects) - address valid_old_base = patch_base; - address valid_old_end = patch_end; - - // after patching, the pointers must point inside this range - // (the requested location of the archive, as mapped at runtime). - address valid_new_base = (address)MetaspaceShared::requested_base_address(); - address valid_new_end = valid_new_base + size; - - log_debug(cds)("Relocating archive from [" INTPTR_FORMAT " - " INTPTR_FORMAT " ] to " - "[" INTPTR_FORMAT " - " INTPTR_FORMAT " ]", p2i(patch_base), p2i(patch_end), - p2i(valid_new_base), p2i(valid_new_end)); - - SharedDataRelocator patcher((address*)patch_base, (address*)patch_end, valid_old_base, valid_old_end, - valid_new_base, valid_new_end, addr_delta, ptrmap); - ptrmap->iterate(&patcher); - ArchivePtrMarker::compact(patcher.max_non_null_offset()); - } -} - void VM_PopulateDumpSharedSpace::doit() { HeapShared::run_full_gc_in_vm_thread(); - CHeapBitMap ptrmap; - MetaspaceShared::initialize_ptr_marker(&ptrmap); // We should no longer allocate anything from the metaspace, so that: // @@ -734,52 +470,24 @@ void VM_PopulateDumpSharedSpace::doit() { // that so we don't have to walk the SystemDictionary again. SystemDictionaryShared::check_excluded_classes(); - StaticArchiveBuilder builder(&_mc_region, &_rw_region, &_ro_region); - builder.set_current_dump_space(&_mc_region); - builder.gather_klasses_and_symbols(); - _global_klass_objects = builder.klasses(); - + StaticArchiveBuilder builder; builder.gather_source_objs(); + builder.reserve_buffer(); - MetaspaceShared::init_misc_code_space(); - builder.allocate_method_trampoline_info(); - builder.allocate_method_trampolines(); - + builder.init_mc_region(); char* cloned_vtables = CppVtables::dumptime_init(); - { - _mc_region.pack(&_rw_region); - builder.set_current_dump_space(&_rw_region); - builder.dump_rw_region(); -#if INCLUDE_CDS_JAVA_HEAP - if (MetaspaceShared::use_full_module_graph()) { - // Archive the ModuleEntry's and PackageEntry's of the 3 built-in loaders - char* start = _rw_region.top(); - ClassLoaderDataShared::allocate_archived_tables(); - ArchiveBuilder::alloc_stats()->record_modules(_rw_region.top() - start, /*read_only*/false); - } -#endif - } - { - _rw_region.pack(&_ro_region); - builder.set_current_dump_space(&_ro_region); - builder.dump_ro_region(); -#if INCLUDE_CDS_JAVA_HEAP - if (MetaspaceShared::use_full_module_graph()) { - char* start = _ro_region.top(); - ClassLoaderDataShared::init_archived_tables(); - ArchiveBuilder::alloc_stats()->record_modules(_ro_region.top() - start, /*read_only*/true); - } -#endif - } - builder.relocate_pointers(); - - dump_shared_symbol_table(builder.symbols()); + builder.dump_rw_region(); + builder.dump_ro_region(); + builder.relocate_metaspaceobj_embedded_pointers(); // Dump supported java heap objects _closed_archive_heap_regions = NULL; _open_archive_heap_regions = NULL; - dump_java_heap_objects(); + dump_java_heap_objects(builder.klasses()); + + builder.relocate_roots(); + dump_shared_symbol_table(builder.symbols()); builder.relocate_vm_classes(); @@ -790,7 +498,6 @@ void VM_PopulateDumpSharedSpace::doit() { builder.make_klasses_shareable(); char* serialized_data = dump_read_only_tables(); - _ro_region.pack(); SystemDictionaryShared::adjust_lambda_proxy_class_dictionary(); @@ -800,44 +507,20 @@ void VM_PopulateDumpSharedSpace::doit() { // relocate the data so that it can be mapped to MetaspaceShared::requested_base_address() // without runtime relocation. - relocate_to_requested_base_address(&ptrmap); - - // Create and write the archive file that maps the shared spaces. + builder.relocate_to_requested(); + // Write the archive file FileMapInfo* mapinfo = new FileMapInfo(true); mapinfo->populate_header(os::vm_allocation_granularity()); mapinfo->set_serialized_data(serialized_data); mapinfo->set_cloned_vtables(cloned_vtables); mapinfo->set_i2i_entry_code_buffers(MetaspaceShared::i2i_entry_code_buffers()); mapinfo->open_for_write(); - size_t bitmap_size_in_bytes; - char* bitmap = MetaspaceShared::write_core_archive_regions(mapinfo, _closed_archive_heap_oopmaps, - _open_archive_heap_oopmaps, - bitmap_size_in_bytes); - _total_closed_archive_region_size = mapinfo->write_archive_heap_regions( - _closed_archive_heap_regions, - _closed_archive_heap_oopmaps, - MetaspaceShared::first_closed_archive_heap_region, - MetaspaceShared::max_closed_archive_heap_region); - _total_open_archive_region_size = mapinfo->write_archive_heap_regions( - _open_archive_heap_regions, - _open_archive_heap_oopmaps, - MetaspaceShared::first_open_archive_heap_region, - MetaspaceShared::max_open_archive_heap_region); - - mapinfo->set_final_requested_base((char*)MetaspaceShared::requested_base_address()); - mapinfo->set_header_crc(mapinfo->compute_header_crc()); - mapinfo->write_header(); - print_region_stats(mapinfo); - mapinfo->close(); - - builder.write_cds_map_to_log(mapinfo, _closed_archive_heap_regions, _open_archive_heap_regions, - bitmap, bitmap_size_in_bytes); - FREE_C_HEAP_ARRAY(char, bitmap); - - if (log_is_enabled(Info, cds)) { - builder.print_stats(int(_ro_region.used()), int(_rw_region.used()), int(_mc_region.used())); - } + builder.write_archive(mapinfo, + _closed_archive_heap_regions, + _open_archive_heap_regions, + _closed_archive_heap_oopmaps, + _open_archive_heap_oopmaps); if (PrintSystemDictionaryAtExit) { SystemDictionary::print(); @@ -854,90 +537,6 @@ void VM_PopulateDumpSharedSpace::doit() { vm_direct_exit(0); } -void VM_PopulateDumpSharedSpace::print_region_stats(FileMapInfo *map_info) { - // Print statistics of all the regions - const size_t bitmap_used = map_info->space_at(MetaspaceShared::bm)->used(); - const size_t bitmap_reserved = map_info->space_at(MetaspaceShared::bm)->used_aligned(); - const size_t total_reserved = _ro_region.reserved() + _rw_region.reserved() + - _mc_region.reserved() + - bitmap_reserved + - _total_closed_archive_region_size + - _total_open_archive_region_size; - const size_t total_bytes = _ro_region.used() + _rw_region.used() + - _mc_region.used() + - bitmap_used + - _total_closed_archive_region_size + - _total_open_archive_region_size; - const double total_u_perc = percent_of(total_bytes, total_reserved); - - _mc_region.print(total_reserved); - _rw_region.print(total_reserved); - _ro_region.print(total_reserved); - print_bitmap_region_stats(bitmap_used, total_reserved); - print_heap_region_stats(_closed_archive_heap_regions, "ca", total_reserved); - print_heap_region_stats(_open_archive_heap_regions, "oa", total_reserved); - - log_debug(cds)("total : " SIZE_FORMAT_W(9) " [100.0%% of total] out of " SIZE_FORMAT_W(9) " bytes [%5.1f%% used]", - total_bytes, total_reserved, total_u_perc); -} - -void VM_PopulateDumpSharedSpace::print_bitmap_region_stats(size_t size, size_t total_size) { - log_debug(cds)("bm space: " SIZE_FORMAT_W(9) " [ %4.1f%% of total] out of " SIZE_FORMAT_W(9) " bytes [100.0%% used]", - size, size/double(total_size)*100.0, size); -} - -void VM_PopulateDumpSharedSpace::print_heap_region_stats(GrowableArray *heap_mem, - const char *name, size_t total_size) { - int arr_len = heap_mem == NULL ? 0 : heap_mem->length(); - for (int i = 0; i < arr_len; i++) { - char* start = (char*)heap_mem->at(i).start(); - size_t size = heap_mem->at(i).byte_size(); - char* top = start + size; - log_debug(cds)("%s%d space: " SIZE_FORMAT_W(9) " [ %4.1f%% of total] out of " SIZE_FORMAT_W(9) " bytes [100.0%% used] at " INTPTR_FORMAT, - name, i, size, size/double(total_size)*100.0, size, p2i(start)); - - } -} - -char* MetaspaceShared::write_core_archive_regions(FileMapInfo* mapinfo, - GrowableArray* closed_oopmaps, - GrowableArray* open_oopmaps, - size_t& bitmap_size_in_bytes) { - // Make sure NUM_CDS_REGIONS (exported in cds.h) agrees with - // MetaspaceShared::n_regions (internal to hotspot). - assert(NUM_CDS_REGIONS == MetaspaceShared::n_regions, "sanity"); - - // mc contains the trampoline code for method entries, which are patched at run time, - // so it needs to be read/write. - write_region(mapinfo, mc, &_mc_region, /*read_only=*/false,/*allow_exec=*/true); - write_region(mapinfo, rw, &_rw_region, /*read_only=*/false,/*allow_exec=*/false); - write_region(mapinfo, ro, &_ro_region, /*read_only=*/true, /*allow_exec=*/false); - - return mapinfo->write_bitmap_region(ArchivePtrMarker::ptrmap(), closed_oopmaps, open_oopmaps, - bitmap_size_in_bytes); -} - -void MetaspaceShared::write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, bool read_only, bool allow_exec) { - mapinfo->write_region(region_idx, dump_region->base(), dump_region->used(), read_only, allow_exec); -} - -// Update a Java object to point its Klass* to the new location after -// shared archive has been compacted. -void MetaspaceShared::relocate_klass_ptr(oop o) { - assert(DumpSharedSpaces, "sanity"); - Klass* k = ArchiveBuilder::get_relocated_klass(o->klass()); - o->set_klass(k); -} - -Klass* MetaspaceShared::get_relocated_klass(Klass *k, bool is_final) { - assert(DumpSharedSpaces, "sanity"); - k = ArchiveBuilder::get_relocated_klass(k); - if (is_final) { - k = (Klass*)(address(k) + final_delta()); - } - return k; -} - static GrowableArray* _loaded_cld = NULL; class CollectCLDClosure : public CLDClosure { @@ -1009,8 +608,15 @@ void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) { } void MetaspaceShared::prepare_for_dumping() { + Arguments::assert_is_dumping_archive(); Arguments::check_unsupported_dumping_properties(); - ClassLoader::initialize_shared_path(); + + EXCEPTION_MARK; + ClassLoader::initialize_shared_path(THREAD); + if (HAS_PENDING_EXCEPTION) { + java_lang_Throwable::print(PENDING_EXCEPTION, tty); + vm_exit_during_initialization("ClassLoader::initialize_shared_path() failed unexpectedly"); + } } // Preload classes from a list, populate the shared spaces and dump to a @@ -1173,7 +779,7 @@ bool MetaspaceShared::try_link_class(InstanceKlass* ik, TRAPS) { } #if INCLUDE_CDS_JAVA_HEAP -void VM_PopulateDumpSharedSpace::dump_java_heap_objects() { +void VM_PopulateDumpSharedSpace::dump_java_heap_objects(GrowableArray* klasses) { if(!HeapShared::is_heap_object_archiving_allowed()) { log_info(cds)( "Archived java heap is not supported as UseG1GC, " @@ -1185,8 +791,8 @@ void VM_PopulateDumpSharedSpace::dump_java_heap_objects() { } // Find all the interned strings that should be dumped. int i; - for (i = 0; i < _global_klass_objects->length(); i++) { - Klass* k = _global_klass_objects->at(i); + for (i = 0; i < klasses->length(); i++) { + Klass* k = klasses->at(i); if (k->is_instance_klass()) { InstanceKlass* ik = InstanceKlass::cast(k); ik->constants()->add_dumped_interned_strings(); @@ -1826,25 +1432,6 @@ bool MetaspaceShared::remap_shared_readonly_as_readwrite() { return true; } -void MetaspaceShared::report_out_of_space(const char* name, size_t needed_bytes) { - // This is highly unlikely to happen on 64-bits because we have reserved a 4GB space. - // On 32-bit we reserve only 256MB so you could run out of space with 100,000 classes - // or so. - _mc_region.print_out_of_space_msg(name, needed_bytes); - _rw_region.print_out_of_space_msg(name, needed_bytes); - _ro_region.print_out_of_space_msg(name, needed_bytes); - - vm_exit_during_initialization(err_msg("Unable to allocate from '%s' region", name), - "Please reduce the number of shared classes."); -} - -// This is used to relocate the pointers so that the base archive can be mapped at -// MetaspaceShared::requested_base_address() without runtime relocation. -intx MetaspaceShared::final_delta() { - return intx(MetaspaceShared::requested_base_address()) // We want the base archive to be mapped to here at runtime - - intx(SharedBaseAddress); // .. but the base archive is mapped at here at dump time -} - bool MetaspaceShared::use_full_module_graph() { #if INCLUDE_CDS_JAVA_HEAP if (ClassLoaderDataShared::is_full_module_graph_loaded()) { @@ -1862,24 +1449,16 @@ bool MetaspaceShared::use_full_module_graph() { } void MetaspaceShared::print_on(outputStream* st) { - if (UseSharedSpaces || DumpSharedSpaces) { + if (UseSharedSpaces) { st->print("CDS archive(s) mapped at: "); - address base; - address top; - if (UseSharedSpaces) { // Runtime - base = (address)MetaspaceObj::shared_metaspace_base(); - address static_top = (address)_shared_metaspace_static_top; - top = (address)MetaspaceObj::shared_metaspace_top(); - st->print("[" PTR_FORMAT "-" PTR_FORMAT "-" PTR_FORMAT "), ", p2i(base), p2i(static_top), p2i(top)); - } else if (DumpSharedSpaces) { // Dump Time - base = (address)_shared_rs.base(); - top = (address)_shared_rs.end(); - st->print("[" PTR_FORMAT "-" PTR_FORMAT "), ", p2i(base), p2i(top)); - } + address base = (address)MetaspaceObj::shared_metaspace_base(); + address static_top = (address)_shared_metaspace_static_top; + address top = (address)MetaspaceObj::shared_metaspace_top(); + st->print("[" PTR_FORMAT "-" PTR_FORMAT "-" PTR_FORMAT "), ", p2i(base), p2i(static_top), p2i(top)); st->print("size " SIZE_FORMAT ", ", top - base); st->print("SharedBaseAddress: " PTR_FORMAT ", ArchiveRelocationMode: %d.", SharedBaseAddress, (int)ArchiveRelocationMode); } else { - st->print("CDS disabled."); + st->print("CDS archive(s) not mapped"); } st->cr(); } diff --git a/src/hotspot/share/memory/metaspaceShared.hpp b/src/hotspot/share/memory/metaspaceShared.hpp index 7e9bed9a991..89fd06c9df5 100644 --- a/src/hotspot/share/memory/metaspaceShared.hpp +++ b/src/hotspot/share/memory/metaspaceShared.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ #ifndef SHARE_MEMORY_METASPACESHARED_HPP #define SHARE_MEMORY_METASPACESHARED_HPP -#include "classfile/compactHashtable.hpp" #include "memory/allocation.hpp" #include "memory/memRegion.hpp" #include "memory/virtualspace.hpp" @@ -33,17 +32,10 @@ #include "utilities/macros.hpp" #include "utilities/resourceHash.hpp" -#define MAX_SHARED_DELTA (0x7FFFFFFF) - -// Metaspace::allocate() requires that all blocks must be aligned with KlassAlignmentInBytes. -// We enforce the same alignment rule in blocks allocated from the shared space. -const int SharedSpaceObjectAlignment = KlassAlignmentInBytes; - -class outputStream; -class CHeapBitMap; class FileMapInfo; -class DumpRegion; -struct ArchiveHeapOopmapInfo; +class outputStream; + +template class GrowableArray; enum MapArchiveResult { MAP_ARCHIVE_SUCCESS, @@ -51,32 +43,14 @@ enum MapArchiveResult { MAP_ARCHIVE_OTHER_FAILURE }; -class MetaspaceSharedStats { -public: - MetaspaceSharedStats() { - memset(this, 0, sizeof(*this)); - } - CompactHashtableStats symbol; - CompactHashtableStats string; -}; - // Class Data Sharing Support class MetaspaceShared : AllStatic { - - // CDS support - - // Note: _shared_rs and _symbol_rs are only used at dump time. - static ReservedSpace _shared_rs; - static VirtualSpace _shared_vs; - static ReservedSpace _symbol_rs; - static VirtualSpace _symbol_vs; - static int _max_alignment; - static MetaspaceSharedStats _stats; + static ReservedSpace _symbol_rs; // used only during -Xshare:dump + static VirtualSpace _symbol_vs; // used only during -Xshare:dump static bool _has_error_classes; static bool _archive_loading_failed; static bool _remapped_readwrite; static address _i2i_entry_code_buffers; - static size_t _core_spaces_size; static void* _shared_metaspace_static_top; static intx _relocation_delta; static char* _requested_base_address; @@ -109,45 +83,19 @@ class MetaspaceShared : AllStatic { static int preload_classes(const char * class_list_path, TRAPS) NOT_CDS_RETURN_(0); - static GrowableArray* collected_klasses(); - - static ReservedSpace* shared_rs() { - CDS_ONLY(return &_shared_rs); - NOT_CDS(return NULL); - } - static Symbol* symbol_rs_base() { return (Symbol*)_symbol_rs.base(); } - static void set_shared_rs(ReservedSpace rs) { - CDS_ONLY(_shared_rs = rs); - } - - static void commit_to(ReservedSpace* rs, VirtualSpace* vs, char* newtop) NOT_CDS_RETURN; - static void initialize_dumptime_shared_and_meta_spaces() NOT_CDS_RETURN; + static void initialize_for_static_dump() NOT_CDS_RETURN; static void initialize_runtime_shared_and_meta_spaces() NOT_CDS_RETURN; static void post_initialize(TRAPS) NOT_CDS_RETURN; static void print_on(outputStream* st); - // Delta of this object from SharedBaseAddress - static uintx object_delta_uintx(void* obj); - - static u4 object_delta_u4(void* obj) { - // offset is guaranteed to be less than MAX_SHARED_DELTA in DumpRegion::expand_top_to() - uintx deltax = object_delta_uintx(obj); - guarantee(deltax <= MAX_SHARED_DELTA, "must be 32-bit offset"); - return (u4)deltax; - } - static void set_archive_loading_failed() { _archive_loading_failed = true; } - static bool is_in_output_space(void* ptr) { - assert(DumpSharedSpaces, "must be"); - return shared_rs()->contains(ptr); - } static bool map_shared_spaces(FileMapInfo* mapinfo) NOT_CDS_RETURN_(false); static void initialize_shared_spaces() NOT_CDS_RETURN; @@ -173,12 +121,6 @@ class MetaspaceShared : AllStatic { static void serialize(SerializeClosure* sc) NOT_CDS_RETURN; - static MetaspaceSharedStats* stats() { - return &_stats; - } - - static void report_out_of_space(const char* name, size_t needed_bytes); - // JVM/TI RedefineClasses() support: // Remap the shared readonly space to shared readwrite, private if // sharing is enabled. Simply returns true if sharing is not enabled @@ -196,76 +138,41 @@ class MetaspaceShared : AllStatic { #if INCLUDE_CDS static size_t reserved_space_alignment(); - static void init_shared_dump_space(DumpRegion* first_space); - static DumpRegion* misc_code_dump_space(); - static DumpRegion* read_write_dump_space(); - static DumpRegion* read_only_dump_space(); - static void pack_dump_space(DumpRegion* current, DumpRegion* next, - ReservedSpace* rs); - static void rewrite_nofast_bytecodes_and_calculate_fingerprints(Thread* thread, InstanceKlass* ik); #endif // Allocate a block of memory from the temporary "symbol" region. static char* symbol_space_alloc(size_t num_bytes); - // Allocate a block of memory from the "mc" or "ro" regions. - static char* misc_code_space_alloc(size_t num_bytes); - static char* read_only_space_alloc(size_t num_bytes); - static char* read_write_space_alloc(size_t num_bytes); - - template - static Array* new_ro_array(int length) { - size_t byte_size = Array::byte_sizeof(length, sizeof(T)); - Array* array = (Array*)read_only_space_alloc(byte_size); - array->initialize(length); - return array; - } - - template - static Array* new_rw_array(int length) { - size_t byte_size = Array::byte_sizeof(length, sizeof(T)); - Array* array = (Array*)read_write_space_alloc(byte_size); - array->initialize(length); - return array; - } - - template - static size_t ro_array_bytesize(int length) { - size_t byte_size = Array::byte_sizeof(length, sizeof(T)); - return align_up(byte_size, SharedSpaceObjectAlignment); - } - static void init_misc_code_space(); static address i2i_entry_code_buffers(); - - static void relocate_klass_ptr(oop o); - static Klass* get_relocated_klass(Klass *k, bool is_final=false); - - static void initialize_ptr_marker(CHeapBitMap* ptrmap); + static void set_i2i_entry_code_buffers(address b); // This is the base address as specified by -XX:SharedBaseAddress during -Xshare:dump. // Both the base/top archives are written using this as their base address. + // + // During static dump: _requested_base_address == SharedBaseAddress. + // + // During dynamic dump: _requested_base_address is not always the same as SharedBaseAddress: + // - SharedBaseAddress is used for *reading the base archive*. I.e., CompactHashtable uses + // it to convert offsets to pointers to Symbols in the base archive. + // The base archive may be mapped to an OS-selected address due to ASLR. E.g., + // you may have SharedBaseAddress == 0x00ff123400000000. + // - _requested_base_address is used for *writing the output archive*. It's usually + // 0x800000000 (unless it was set by -XX:SharedBaseAddress during -Xshare:dump). static char* requested_base_address() { return _requested_base_address; } // Non-zero if the archive(s) need to be mapped a non-default location due to ASLR. static intx relocation_delta() { return _relocation_delta; } - static intx final_delta(); + static bool use_windows_memory_mapping() { const bool is_windows = (NOT_WINDOWS(false) WINDOWS_ONLY(true)); //const bool is_windows = true; // enable this to allow testing the windows mmap semantics on Linux, etc. return is_windows; } - // Returns the bitmap region which is allocated from C heap. - // Caller must free it with FREE_C_HEAP_ARRAY() - static char* write_core_archive_regions(FileMapInfo* mapinfo, - GrowableArray* closed_oopmaps, - GrowableArray* open_oopmaps, - size_t& bitmap_size_in_bytes); - // Can we skip some expensive operations related to modules? static bool use_optimized_module_handling() { return NOT_CDS(false) CDS_ONLY(_use_optimized_module_handling); } static void disable_optimized_module_handling() { _use_optimized_module_handling = false; } @@ -275,10 +182,6 @@ class MetaspaceShared : AllStatic { static void disable_full_module_graph() { _use_full_module_graph = false; } private: -#if INCLUDE_CDS - static void write_region(FileMapInfo* mapinfo, int region_idx, DumpRegion* dump_region, - bool read_only, bool allow_exec); -#endif static void read_extra_data(const char* filename, TRAPS) NOT_CDS_RETURN; static FileMapInfo* open_static_archive(); static FileMapInfo* open_dynamic_archive(); diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index 23a780bb4b6..968f44e324f 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -66,6 +66,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/init.hpp" #include "runtime/java.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/thread.inline.hpp" #include "runtime/timerTrace.hpp" #include "services/memoryService.hpp" @@ -1262,7 +1263,6 @@ Method* LatestMethodCache::get_method() { return m; } - #ifdef ASSERT // Release dummy object(s) at bottom of heap bool Universe::release_fullgc_alot_dummy() { @@ -1281,4 +1281,12 @@ bool Universe::release_fullgc_alot_dummy() { return true; } +bool Universe::is_gc_active() { + return heap()->is_gc_active(); +} + +bool Universe::is_in_heap(const void* p) { + return heap()->is_in(p); +} + #endif // ASSERT diff --git a/src/hotspot/share/memory/universe.hpp b/src/hotspot/share/memory/universe.hpp index e45aa85bc73..014dd4ea1a6 100644 --- a/src/hotspot/share/memory/universe.hpp +++ b/src/hotspot/share/memory/universe.hpp @@ -315,6 +315,10 @@ class Universe: AllStatic { // The particular choice of collected heap. static CollectedHeap* heap() { return _collectedHeap; } + DEBUG_ONLY(static bool is_gc_active();) + DEBUG_ONLY(static bool is_in_heap(const void* p);) + DEBUG_ONLY(static bool is_in_heap_or_null(const void* p) { return p == NULL || is_in_heap(p); }) + // Reserve Java heap and determine CompressedOops mode static ReservedHeapSpace reserve_heap(size_t heap_size, size_t alignment); diff --git a/src/hotspot/share/memory/virtualspace.cpp b/src/hotspot/share/memory/virtualspace.cpp index db8bb8146e4..0d16ffcd37d 100644 --- a/src/hotspot/share/memory/virtualspace.cpp +++ b/src/hotspot/share/memory/virtualspace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ #include "runtime/os.inline.hpp" #include "services/memTracker.hpp" #include "utilities/align.hpp" +#include "utilities/formatBuffer.hpp" #include "utilities/powerOfTwo.hpp" // ReservedSpace diff --git a/src/hotspot/share/oops/accessBackend.inline.hpp b/src/hotspot/share/oops/accessBackend.inline.hpp index a64a18abb3c..3d971efe618 100644 --- a/src/hotspot/share/oops/accessBackend.inline.hpp +++ b/src/hotspot/share/oops/accessBackend.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "oops/access.hpp" #include "oops/accessBackend.hpp" +#include "oops/arrayOop.hpp" #include "oops/compressedOops.inline.hpp" #include "oops/oopsHierarchy.hpp" #include "runtime/atomic.hpp" diff --git a/src/hotspot/share/oops/array.hpp b/src/hotspot/share/oops/array.hpp index f383564ac84..589ac22d33e 100644 --- a/src/hotspot/share/oops/array.hpp +++ b/src/hotspot/share/oops/array.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,8 @@ template class Array: public MetaspaceObj { + friend class ArchiveBuilder; friend class MetadataFactory; - friend class MetaspaceShared; friend class VMStructs; friend class JVMCIVMStructs; friend class MethodHandleCompiler; // special case diff --git a/src/hotspot/share/oops/compiledICHolder.hpp b/src/hotspot/share/oops/compiledICHolder.hpp index a1932cba56c..b3d0c8715bf 100644 --- a/src/hotspot/share/oops/compiledICHolder.hpp +++ b/src/hotspot/share/oops/compiledICHolder.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,16 +71,7 @@ class CompiledICHolder : public CHeapObj { CompiledICHolder* next() { return _next; } void set_next(CompiledICHolder* n) { _next = n; } - inline bool is_loader_alive() { - Klass* k = _is_metadata_method ? ((Method*)_holder_metadata)->method_holder() : (Klass*)_holder_metadata; - if (!k->is_loader_alive()) { - return false; - } - if (!_holder_klass->is_loader_alive()) { - return false; - } - return true; - } + inline bool is_loader_alive(); // Verify void verify_on(outputStream* st); diff --git a/src/hotspot/share/oops/compiledICHolder.inline.hpp b/src/hotspot/share/oops/compiledICHolder.inline.hpp new file mode 100644 index 00000000000..4a5531531f0 --- /dev/null +++ b/src/hotspot/share/oops/compiledICHolder.inline.hpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_OOPS_COMPILEDICHOLDER_INLINE_HPP +#define SHARE_OOPS_COMPILEDICHOLDER_INLINE_HPP + +#include "oops/compiledICHolder.hpp" +#include "oops/klass.inline.hpp" + +inline bool CompiledICHolder::is_loader_alive() { + Klass* k = _is_metadata_method ? ((Method*)_holder_metadata)->method_holder() : (Klass*)_holder_metadata; + if (!k->is_loader_alive()) { + return false; + } + if (!_holder_klass->is_loader_alive()) { + return false; + } + return true; +} + +#endif // SHARE_OOPS_COMPILEDICHOLDER_INLINE_HPP diff --git a/src/hotspot/share/oops/compressedOops.hpp b/src/hotspot/share/oops/compressedOops.hpp index c12f6bd197b..83f18138b5a 100644 --- a/src/hotspot/share/oops/compressedOops.hpp +++ b/src/hotspot/share/oops/compressedOops.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -181,10 +181,13 @@ class CompressedKlassPointers : public AllStatic { static bool is_null(Klass* v) { return v == NULL; } static bool is_null(narrowKlass v) { return v == 0; } + static inline Klass* decode_raw(narrowKlass v, address base); static inline Klass* decode_raw(narrowKlass v); static inline Klass* decode_not_null(narrowKlass v); + static inline Klass* decode_not_null(narrowKlass v, address base); static inline Klass* decode(narrowKlass v); static inline narrowKlass encode_not_null(Klass* v); + static inline narrowKlass encode_not_null(Klass* v, address base); static inline narrowKlass encode(Klass* v); }; diff --git a/src/hotspot/share/oops/compressedOops.inline.hpp b/src/hotspot/share/oops/compressedOops.inline.hpp index 920e87703b4..597c3e96bbd 100644 --- a/src/hotspot/share/oops/compressedOops.inline.hpp +++ b/src/hotspot/share/oops/compressedOops.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,11 @@ #ifndef SHARE_OOPS_COMPRESSEDOOPS_INLINE_HPP #define SHARE_OOPS_COMPRESSEDOOPS_INLINE_HPP -#include "gc/shared/collectedHeap.hpp" #include "memory/universe.hpp" #include "oops/compressedOops.hpp" #include "oops/oop.hpp" #include "utilities/align.hpp" +#include "utilities/globalDefinitions.hpp" // Functions for encoding and decoding compressed oops. // If the oops are compressed, the type passed to these overloaded functions @@ -54,7 +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)); + assert(Universe::is_in_heap(result), "object not in heap " PTR_FORMAT, p2i((void*) result)); return result; } @@ -78,12 +78,12 @@ inline narrowOop CompressedOops::encode(oop v) { } inline oop CompressedOops::decode_not_null(oop v) { - assert(Universe::heap()->is_in(v), "object not in heap " PTR_FORMAT, p2i((void*) v)); + assert(Universe::is_in_heap(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)); + assert(Universe::is_in_heap_or_null(v), "object not in heap " PTR_FORMAT, p2i((void*) v)); return v; } @@ -117,12 +117,20 @@ static inline bool check_alignment(Klass* v) { } inline Klass* CompressedKlassPointers::decode_raw(narrowKlass v) { - return (Klass*)(void*)((uintptr_t)base() +((uintptr_t)v << shift())); - } + return decode_raw(v, base()); +} + +inline Klass* CompressedKlassPointers::decode_raw(narrowKlass v, address narrow_base) { + return (Klass*)(void*)((uintptr_t)narrow_base +((uintptr_t)v << shift())); +} inline Klass* CompressedKlassPointers::decode_not_null(narrowKlass v) { + return decode_not_null(v, base()); +} + +inline Klass* CompressedKlassPointers::decode_not_null(narrowKlass v, address narrow_base) { assert(!is_null(v), "narrow klass value can never be zero"); - Klass* result = decode_raw(v); + Klass* result = decode_raw(v, narrow_base); assert(check_alignment(result), "address not aligned: " INTPTR_FORMAT, p2i((void*) result)); return result; } @@ -132,13 +140,17 @@ inline Klass* CompressedKlassPointers::decode(narrowKlass v) { } inline narrowKlass CompressedKlassPointers::encode_not_null(Klass* v) { + return encode_not_null(v, base()); +} + +inline narrowKlass CompressedKlassPointers::encode_not_null(Klass* v, address narrow_base) { assert(!is_null(v), "klass value can never be zero"); assert(check_alignment(v), "Address not aligned"); - uint64_t pd = (uint64_t)(pointer_delta((void*)v, base(), 1)); + uint64_t pd = (uint64_t)(pointer_delta((void*)v, narrow_base, 1)); assert(KlassEncodingMetaspaceMax > pd, "change encoding max if new encoding"); uint64_t result = pd >> shift(); assert((result & CONST64(0xffffffff00000000)) == 0, "narrow klass pointer overflow"); - assert(decode(result) == v, "reversibility"); + assert(decode_not_null(result, narrow_base) == v, "reversibility"); return (narrowKlass)result; } diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index 0a39751a8e5..0482b1e3c32 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -39,7 +39,6 @@ #include "memory/heapShared.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" -#include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" @@ -279,7 +278,7 @@ void ConstantPool::klass_at_put(int class_index, Klass* k) { #if INCLUDE_CDS_JAVA_HEAP // Archive the resolved references -void ConstantPool::archive_resolved_references(Thread* THREAD) { +void ConstantPool::archive_resolved_references() { if (_cache == NULL) { return; // nothing to do } @@ -314,7 +313,7 @@ void ConstantPool::archive_resolved_references(Thread* THREAD) { } } - oop archived = HeapShared::archive_heap_object(rr, THREAD); + oop archived = HeapShared::archive_heap_object(rr); // If the resolved references array is not archived (too large), // the 'archived' object is NULL. No need to explicitly check // the return value of archive_heap_object here. At runtime, the diff --git a/src/hotspot/share/oops/constantPool.hpp b/src/hotspot/share/oops/constantPool.hpp index 410a011d329..003b5fd8212 100644 --- a/src/hotspot/share/oops/constantPool.hpp +++ b/src/hotspot/share/oops/constantPool.hpp @@ -748,7 +748,7 @@ class ConstantPool : public Metadata { } // CDS support - void archive_resolved_references(Thread *THREAD) NOT_CDS_JAVA_HEAP_RETURN; + void archive_resolved_references() NOT_CDS_JAVA_HEAP_RETURN; void add_dumped_interned_strings() NOT_CDS_JAVA_HEAP_RETURN; void resolve_class_constants(TRAPS) NOT_CDS_JAVA_HEAP_RETURN; void remove_unshareable_info(); diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp index eb4e367f08e..26d3b63fecd 100644 --- a/src/hotspot/share/oops/cpCache.cpp +++ b/src/hotspot/share/oops/cpCache.cpp @@ -36,7 +36,6 @@ #include "memory/heapShared.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" -#include "memory/metaspaceShared.hpp" #include "memory/resourceArea.hpp" #include "oops/access.inline.hpp" #include "oops/compressedOops.hpp" diff --git a/src/hotspot/share/oops/flatArrayOop.hpp b/src/hotspot/share/oops/flatArrayOop.hpp index 14afcb13d4c..24dfd5c45ab 100644 --- a/src/hotspot/share/oops/flatArrayOop.hpp +++ b/src/hotspot/share/oops/flatArrayOop.hpp @@ -27,6 +27,7 @@ #include "oops/arrayOop.hpp" #include "oops/klass.hpp" +#include "runtime/handles.hpp" // A flatArrayOop is an array containing inline types (may include flatten embedded oop elements). diff --git a/src/hotspot/share/oops/flatArrayOop.inline.hpp b/src/hotspot/share/oops/flatArrayOop.inline.hpp index 4067cc80f9f..93711dd5aa6 100644 --- a/src/hotspot/share/oops/flatArrayOop.inline.hpp +++ b/src/hotspot/share/oops/flatArrayOop.inline.hpp @@ -52,7 +52,7 @@ inline oop flatArrayOopDesc::value_alloc_copy_from_index(flatArrayHandle vah, in return vklass->default_value(); } else { oop buf = vklass->allocate_instance_buffer(CHECK_NULL); - vklass->inline_copy_payload_to_new_oop(vah->value_at_addr(index, vaklass->layout_helper()) ,buf); + vklass->inline_copy_payload_to_new_oop(vah->value_at_addr(index, vaklass->layout_helper()), buf); return buf; } } @@ -60,12 +60,8 @@ inline oop flatArrayOopDesc::value_alloc_copy_from_index(flatArrayHandle vah, in inline void flatArrayOopDesc::value_copy_from_index(int index, oop dst) const { FlatArrayKlass* vaklass = FlatArrayKlass::cast(klass()); InlineKlass* vklass = vaklass->element_klass(); - if (vklass->is_empty_inline_type()) { - return; // Assumes dst was a new and clean buffer (OptoRuntime::load_unknown_inline()) - } else { - void* src = value_at_addr(index, vaklass->layout_helper()); - return vklass->inline_copy_payload_to_new_oop(src ,dst); - } + void* src = value_at_addr(index, vaklass->layout_helper()); + return vklass->inline_copy_payload_to_new_oop(src, dst); } inline void flatArrayOopDesc::value_copy_to_index(oop src, int index) const { diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index ed3e402d328..5f1dac9cf9e 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -3108,7 +3108,7 @@ void InstanceKlass::set_package(ClassLoaderData* loader_data, PackageEntry* pkg_ // in an unnamed module. It is also used to indicate (for all packages whose // classes are loaded by the boot loader) that at least one of the package's // classes has been loaded. -void InstanceKlass::set_classpath_index(s2 path_index, TRAPS) { +void InstanceKlass::set_classpath_index(s2 path_index) { if (_package_entry != NULL) { DEBUG_ONLY(PackageEntryTable* pkg_entry_tbl = ClassLoaderData::the_null_class_loader_data()->packages();) assert(pkg_entry_tbl->lookup_only(_package_entry->name()) == _package_entry, "Should be same"); diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 2e2df89ed99..b02ae8dca02 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ #ifndef SHARE_OOPS_INSTANCEKLASS_HPP #define SHARE_OOPS_INSTANCEKLASS_HPP -#include "classfile/classLoaderData.hpp" #include "code/vmreg.hpp" #include "memory/referenceType.hpp" #include "oops/annotations.hpp" @@ -640,7 +639,7 @@ class InstanceKlass: public Klass { // packages returned by get_system_packages(). // For packages whose classes are loaded from the boot loader class path, the // classpath_index indicates which entry on the boot loader class path. - void set_classpath_index(s2 path_index, TRAPS); + void set_classpath_index(s2 path_index); bool is_same_class_package(const Klass* class2) const; bool is_same_class_package(oop other_class_loader, const Symbol* other_class_name) const; diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index 7605548bfa3..48efc9b2197 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -38,7 +38,6 @@ #include "memory/heapShared.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceClosure.hpp" -#include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index d0681f35a7f..7df6cdef977 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ #ifndef SHARE_OOPS_KLASS_HPP #define SHARE_OOPS_KLASS_HPP -#include "classfile/classLoaderData.hpp" #include "memory/iterator.hpp" #include "memory/memRegion.hpp" #include "oops/markWord.hpp" @@ -68,6 +67,7 @@ const uint KLASS_ID_COUNT = 7; // Forward declarations. template class Array; template class GrowableArray; +class ClassLoaderData; class fieldDescriptor; class klassVtable; class ModuleEntry; @@ -528,11 +528,7 @@ class Klass : public Metadata { oop class_loader() const; - // This loads the klass's holder as a phantom. This is useful when a weak Klass - // pointer has been "peeked" and then must be kept alive before it may - // be used safely. All uses of klass_holder need to apply the appropriate barriers, - // except during GC. - oop klass_holder() const { return class_loader_data()->holder_phantom(); } + inline oop klass_holder() const; protected: virtual Klass* array_klass_impl(bool or_null, int rank, TRAPS); @@ -667,11 +663,11 @@ class Klass : public Metadata { void set_is_shared() { _access_flags.set_is_shared_class(); } bool is_hidden() const { return access_flags().is_hidden_class(); } void set_is_hidden() { _access_flags.set_is_hidden_class(); } - bool is_non_strong_hidden() const { return access_flags().is_hidden_class() && - class_loader_data()->has_class_mirror_holder(); } bool is_value_based() { return _access_flags.is_value_based_class(); } void set_is_value_based() { _access_flags.set_is_value_based_class(); } + inline bool is_non_strong_hidden() const; + bool is_cloneable() const; void set_is_cloneable(); @@ -707,10 +703,7 @@ class Klass : public Metadata { virtual void metaspace_pointers_do(MetaspaceClosure* iter); virtual MetaspaceObj::Type type() const { return ClassType; } - // Iff the class loader (or mirror for unsafe anonymous classes) is alive the - // Klass is considered alive. This is safe to call before the CLD is marked as - // unloading, and hence during concurrent class unloading. - bool is_loader_alive() const { return class_loader_data()->is_alive(); } + inline bool is_loader_alive() const; void clean_subklass(); diff --git a/src/hotspot/share/oops/klass.inline.hpp b/src/hotspot/share/oops/klass.inline.hpp index 7ecf176b0d4..627711c4da9 100644 --- a/src/hotspot/share/oops/klass.inline.hpp +++ b/src/hotspot/share/oops/klass.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,26 @@ #include "oops/klass.hpp" #include "oops/markWord.hpp" +// This loads the klass's holder as a phantom. This is useful when a weak Klass +// pointer has been "peeked" and then must be kept alive before it may +// be used safely. All uses of klass_holder need to apply the appropriate barriers, +// except during GC. +inline oop Klass::klass_holder() const { + return class_loader_data()->holder_phantom(); +} + +inline bool Klass::is_non_strong_hidden() const { + return access_flags().is_hidden_class() && + class_loader_data()->has_class_mirror_holder(); +} + +// Iff the class loader (or mirror for unsafe anonymous classes) is alive the +// Klass is considered alive. This is safe to call before the CLD is marked as +// unloading, and hence during concurrent class unloading. +inline bool Klass::is_loader_alive() const { + return class_loader_data()->is_alive(); +} + inline void Klass::set_prototype_header(markWord header) { assert(!is_inline_klass() || header.is_inline_type(), "Unexpected prototype"); assert(!UseBiasedLocking || !header.has_bias_pattern() || is_instance_klass(), "biased locking currently only supported for Java instances"); diff --git a/src/hotspot/share/oops/methodData.cpp b/src/hotspot/share/oops/methodData.cpp index eab53cec49a..a829aa526d6 100644 --- a/src/hotspot/share/oops/methodData.cpp +++ b/src/hotspot/share/oops/methodData.cpp @@ -32,6 +32,7 @@ #include "interpreter/linkResolver.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/resourceArea.hpp" +#include "oops/klass.inline.hpp" #include "oops/methodData.inline.hpp" #include "prims/jvmtiRedefineClasses.hpp" #include "runtime/arguments.hpp" @@ -1300,7 +1301,7 @@ void MethodData::initialize() { object_size += extra_size + arg_data_size; int parms_cell = ParametersTypeData::compute_cell_count(method()); - // If we are profiling parameters, we reserver an area near the end + // If we are profiling parameters, we reserved an area near the end // of the MDO after the slots for bytecodes (because there's no bci // for method entry so they don't fit with the framework for the // profiling of bytecodes). We store the offset within the MDO of diff --git a/src/hotspot/share/oops/methodData.hpp b/src/hotspot/share/oops/methodData.hpp index e572ef38829..21e79e3d63a 100644 --- a/src/hotspot/share/oops/methodData.hpp +++ b/src/hotspot/share/oops/methodData.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ #include "oops/method.hpp" #include "oops/oop.hpp" #include "runtime/atomic.hpp" +#include "runtime/mutex.hpp" #include "utilities/align.hpp" #include "utilities/copy.hpp" diff --git a/src/hotspot/share/oops/objArrayKlass.hpp b/src/hotspot/share/oops/objArrayKlass.hpp index 96a42dc7971..9734e389fda 100644 --- a/src/hotspot/share/oops/objArrayKlass.hpp +++ b/src/hotspot/share/oops/objArrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,11 @@ #ifndef SHARE_OOPS_OBJARRAYKLASS_HPP #define SHARE_OOPS_OBJARRAYKLASS_HPP -#include "classfile/classLoaderData.hpp" #include "oops/arrayKlass.hpp" #include "utilities/macros.hpp" +class ClassLoaderData; + // ObjArrayKlass is the klass for objArrays class ObjArrayKlass : public ArrayKlass { diff --git a/src/hotspot/share/oops/oop.cpp b/src/hotspot/share/oops/oop.cpp index 158ed06f984..2de1dbff7aa 100644 --- a/src/hotspot/share/oops/oop.cpp +++ b/src/hotspot/share/oops/oop.cpp @@ -146,6 +146,14 @@ bool oopDesc::has_klass_gap() { return UseCompressedClassPointers; } +#if INCLUDE_CDS_JAVA_HEAP +void oopDesc::set_narrow_klass(narrowKlass nk) { + assert(DumpSharedSpaces, "Used by CDS only. Do not abuse!"); + assert(UseCompressedClassPointers, "must be"); + _metadata._compressed_klass = nk; +} +#endif + void* oopDesc::load_klass_raw(oop obj) { if (UseCompressedClassPointers) { narrowKlass narrow_klass = obj->_metadata._compressed_klass; diff --git a/src/hotspot/share/oops/oop.hpp b/src/hotspot/share/oops/oop.hpp index ec6fedd74e4..c3f10dfbba4 100644 --- a/src/hotspot/share/oops/oop.hpp +++ b/src/hotspot/share/oops/oop.hpp @@ -86,6 +86,7 @@ class oopDesc { inline Klass* klass_or_null() const; inline Klass* klass_or_null_acquire() const; + void set_narrow_klass(narrowKlass nk) NOT_CDS_JAVA_HEAP_RETURN; inline void set_klass(Klass* k); static inline void release_set_klass(HeapWord* mem, Klass* k); diff --git a/src/hotspot/share/oops/oop.inline.hpp b/src/hotspot/share/oops/oop.inline.hpp index a97e47b12c0..e26f20e70e5 100644 --- a/src/hotspot/share/oops/oop.inline.hpp +++ b/src/hotspot/share/oops/oop.inline.hpp @@ -25,7 +25,6 @@ #ifndef SHARE_OOPS_OOP_INLINE_HPP #define SHARE_OOPS_OOP_INLINE_HPP -#include "gc/shared/collectedHeap.hpp" #include "memory/universe.hpp" #include "oops/access.inline.hpp" #include "oops/arrayKlass.hpp" @@ -33,10 +32,14 @@ #include "oops/compressedOops.inline.hpp" #include "oops/markWord.inline.hpp" #include "oops/oop.hpp" +#include "oops/oopsHierarchy.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" +#include "runtime/globals.hpp" #include "utilities/align.hpp" +#include "utilities/debug.hpp" #include "utilities/macros.hpp" +#include "utilities/globalDefinitions.hpp" // Implementation of all inlined member functions defined in oop.hpp // We need a separate file to avoid circular references @@ -185,7 +188,7 @@ int oopDesc::size_given_klass(Klass* klass) { // disjunct below to fail if the two comparands are computed across such // a concurrent change. assert((s == klass->oop_size(this)) || - (Universe::heap()->is_gc_active() && is_objArray() && is_forwarded() && (get_UseParallelGC() || get_UseG1GC())), + (Universe::is_gc_active() && is_objArray() && is_forwarded() && (get_UseParallelGC() || get_UseG1GC())), "wrong array object size"); } else { // Must be zero, so bite the bullet and take the virtual call. diff --git a/src/hotspot/share/oops/typeArrayKlass.hpp b/src/hotspot/share/oops/typeArrayKlass.hpp index f0fea59afd2..0c57c8a375f 100644 --- a/src/hotspot/share/oops/typeArrayKlass.hpp +++ b/src/hotspot/share/oops/typeArrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,10 @@ #ifndef SHARE_OOPS_TYPEARRAYKLASS_HPP #define SHARE_OOPS_TYPEARRAYKLASS_HPP -#include "classfile/classLoaderData.hpp" #include "oops/arrayKlass.hpp" +class ClassLoaderData; + // A TypeArrayKlass is the klass of a typeArray // It contains the type and size of the elements diff --git a/src/hotspot/share/opto/idealGraphPrinter.cpp b/src/hotspot/share/opto/idealGraphPrinter.cpp index c7f1a17aa8c..11dfc43a79f 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.cpp +++ b/src/hotspot/share/opto/idealGraphPrinter.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ #include "opto/parse.hpp" #include "runtime/threadCritical.hpp" #include "runtime/threadSMR.hpp" +#include "utilities/stringUtils.hpp" #ifndef PRODUCT @@ -378,9 +379,39 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { print_prop("block", C->cfg()->get_block(0)->_pre_order); } else { print_prop("block", block->_pre_order); + // Print estimated execution frequency, normalized within a [0,1] range. + buffer[0] = 0; + stringStream freq(buffer, sizeof(buffer) - 1); + // Higher precision has no practical effect in visualizations. + freq.print("%.8f", block->_freq / _max_freq); + assert(freq.size() < sizeof(buffer), "size in range"); + // Enforce dots as decimal separators, as required by IGV. + StringUtils::replace_no_expand(buffer, ",", "."); + print_prop("frequency", buffer); } } + switch (t->category()) { + case Type::Category::Data: + print_prop("category", "data"); + break; + case Type::Category::Memory: + print_prop("category", "memory"); + break; + case Type::Category::Mixed: + print_prop("category", "mixed"); + break; + case Type::Category::Control: + print_prop("category", "control"); + break; + case Type::Category::Other: + print_prop("category", "other"); + break; + case Type::Category::Undef: + print_prop("category", "undef"); + break; + } + const jushort flags = node->flags(); if (flags & Node::Flag_is_Copy) { print_prop("is_copy", "true"); @@ -649,6 +680,16 @@ void IdealGraphPrinter::print(const char *name, Node *node) { VectorSet temp_set; head(NODES_ELEMENT); + if (C->cfg() != NULL) { + // Compute the maximum estimated frequency in the current graph. + _max_freq = 1.0e-6; + for (uint i = 0; i < C->cfg()->number_of_blocks(); i++) { + Block* block = C->cfg()->get_block(i); + if (block->_freq > _max_freq) { + _max_freq = block->_freq; + } + } + } walk_nodes(node, false, &temp_set); tail(NODES_ELEMENT); diff --git a/src/hotspot/share/opto/idealGraphPrinter.hpp b/src/hotspot/share/opto/idealGraphPrinter.hpp index 48da2b2970f..6d8db169b9f 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.hpp +++ b/src/hotspot/share/opto/idealGraphPrinter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,6 +92,7 @@ class IdealGraphPrinter : public CHeapObj { PhaseChaitin* _chaitin; bool _traverse_outs; Compile *C; + double _max_freq; void print_method(ciMethod *method, int bci, InlineTree *tree); void print_inline_tree(InlineTree *tree); diff --git a/src/hotspot/share/opto/locknode.cpp b/src/hotspot/share/opto/locknode.cpp index 1b65d5f59db..20e7763734f 100644 --- a/src/hotspot/share/opto/locknode.cpp +++ b/src/hotspot/share/opto/locknode.cpp @@ -184,7 +184,7 @@ void Parse::do_monitor_enter() { Node* obj = peek(); const Type* obj_type = gvn().type(obj); - if (obj_type->isa_inlinetype() && !obj_type->is_inlinetypeptr()) { + if (obj_type->isa_inlinetype() || obj_type->is_inlinetypeptr()) { uncommon_trap(Deoptimization::Reason_class_check, Deoptimization::Action_none); return; diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 3be00bc8991..38d98fb0fcb 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -291,6 +291,7 @@ IdealLoopTree* PhaseIdealLoop::insert_outer_loop(IdealLoopTree* loop, LoopNode* loop->_parent = outer_ilt; loop->_next = NULL; loop->_nest++; + assert(loop->_nest <= SHRT_MAX, "sanity"); return outer_ilt; } @@ -2614,6 +2615,7 @@ bool IdealLoopTree::is_member(const IdealLoopTree *l) const { //------------------------------set_nest--------------------------------------- // Set loop tree nesting depth. Accumulate _has_call bits. int IdealLoopTree::set_nest( uint depth ) { + assert(depth <= SHRT_MAX, "sanity"); _nest = depth; int bits = _has_call; if( _child ) bits |= _child->set_nest(depth+1); diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 83cd0d22540..f1f377de844 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -614,7 +614,7 @@ class IdealLoopTree : public ResourceObj { Node_List _body; // Loop body for inner loops - uint8_t _nest; // Nesting depth + uint16_t _nest; // Nesting depth uint8_t _irreducible:1, // True if irreducible _has_call:1, // True if has call safepoint _has_sfpt:1, // True if has non-call safepoint @@ -1613,6 +1613,8 @@ class PhaseIdealLoop : public PhaseTransform { void check_long_counted_loop(IdealLoopTree* loop, Node* x) NOT_DEBUG_RETURN; LoopNode* create_inner_head(IdealLoopTree* loop, LongCountedLoopNode* head, LongCountedLoopEndNode* exit_test); + + bool is_safe_load_ctrl(Node* ctrl); }; diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index 6f488beb1a4..658236bdab7 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -1592,7 +1592,7 @@ void PhaseIdealLoop::split_if_with_blocks_post(Node *n) { // If n is a load, and the late control is the same as the current // control, then the cloning of n is a pointless exercise, because // GVN will ensure that we end up where we started. - if (!n->is_Load() || late_load_ctrl != n_ctrl) { + if (!n->is_Load() || (late_load_ctrl != n_ctrl && is_safe_load_ctrl(late_load_ctrl))) { Node* outer_loop_clone = NULL; for (DUIterator_Last jmin, j = n->last_outs(jmin); j >= jmin; ) { Node *u = n->last_out(j); // Clone private computation per use @@ -1702,6 +1702,13 @@ void PhaseIdealLoop::split_if_with_blocks_post(Node *n) { } } +bool PhaseIdealLoop::is_safe_load_ctrl(Node* ctrl) { + if (ctrl->is_Proj() && ctrl->in(0)->is_Call() && ctrl->has_out_with(Op_Catch)) { + return false; + } + return true; +} + //------------------------------split_if_with_blocks--------------------------- // Check for aggressive application of 'split-if' optimization, // using basic block level info. diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 83e46bbdae9..2bd1163f712 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -2132,9 +2132,17 @@ const Type* LoadNode::Value(PhaseGVN* phase) const { return Type::get_zero_type(_type->basic_type()); } } - if (!EnableValhalla) { // CMH: Fix JDK-8255045 - Node* alloc = is_new_object_mark_load(phase); - if (alloc != NULL && !(alloc->Opcode() == Op_Allocate && UseBiasedLocking)) { + Node* alloc = is_new_object_mark_load(phase); + if (alloc != NULL && !(alloc->Opcode() == Op_Allocate && UseBiasedLocking)) { + if (EnableValhalla) { + // The mark word may contain property bits (inline, flat, null-free) + Node* klass_node = alloc->in(AllocateNode::KlassNode); + const TypeKlassPtr* tkls = phase->type(klass_node)->is_klassptr(); + ciKlass* klass = tkls->klass(); + if (klass != NULL && klass->is_loaded() && tkls->klass_is_exact()) { + return TypeX::make(klass->prototype_header().value()); + } + } else { return TypeX::make(markWord::prototype().value()); } } diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index eec17056cb6..255fc9ef62d 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -49,6 +49,7 @@ #include "oops/flatArrayKlass.hpp" #include "oops/flatArrayOop.inline.hpp" #include "oops/objArrayKlass.hpp" +#include "oops/klass.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayOop.inline.hpp" #include "opto/ad.hpp" diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index af9d6faac5b..90ce0f99c51 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -2316,18 +2316,13 @@ Node* SuperWord::pick_mem_state(Node_List* pk) { assert(current->is_Mem() && in_bb(current), "unexpected memory"); assert(current != first_mem, "corrupted memory graph"); if (!independent(current, ld)) { -#ifdef ASSERT - // Added assertion code since no case has been observed that should pick the first memory state. - // Remove the assertion code whenever we find a (valid) case that really needs the first memory state. - pk->dump(); - first_mem->dump(); - last_mem->dump(); - current->dump(); - ld->dump(); - ld->in(MemNode::Memory)->dump(); - assert(false, "never observed that first memory should be picked"); -#endif - return first_mem; // A later store depends on this load, pick memory state of first load + // A later store depends on this load, pick the memory state of the first load. This can happen, for example, + // if a load pack has interleaving stores that are part of a store pack which, however, is removed at the pack + // filtering stage. This leaves us with only a load pack for which we cannot take the memory state of the + // last load as the remaining unvectorized stores could interfere since they have a dependency to the loads. + // Some stores could be executed before the load vector resulting in a wrong result. We need to take the + // memory state of the first load to prevent this. + return first_mem; } } } @@ -3217,21 +3212,23 @@ void SuperWord::compute_vector_element_type() { } } if (same_type) { - // For right shifts of small integer types (bool, byte, char, short) - // we need precise information about sign-ness. Only Load nodes have - // this information because Store nodes are the same for signed and - // unsigned values. And any arithmetic operation after a load may - // expand a value to signed Int so such right shifts can't be used - // because vector elements do not have upper bits of Int. + // In any Java arithmetic operation, operands of small integer types + // (boolean, byte, char & short) should be promoted to int first. As + // vector elements of small types don't have upper bits of int, for + // RShiftI or AbsI operations, the compiler has to know the precise + // signedness info of the 1st operand. These operations shouldn't be + // vectorized if the signedness info is imprecise. const Type* vt = vtn; - if (VectorNode::is_shift(in)) { + int op = in->Opcode(); + if (VectorNode::is_shift_opcode(op) || op == Op_AbsI) { Node* load = in->in(1); if (load->is_Load() && in_bb(load) && (velt_type(load)->basic_type() == T_INT)) { + // Only Load nodes distinguish signed (LoadS/LoadB) and unsigned + // (LoadUS/LoadUB) values. Store nodes only have one version. vt = velt_type(load); - } else if (in->Opcode() != Op_LShiftI) { - // Widen type to Int to avoid creation of right shift vector - // (align + data_size(s1) check in stmts_can_pack() will fail). - // Note, left shifts work regardless type. + } else if (op != Op_LShiftI) { + // Widen type to int to avoid the creation of vector nodes. Note + // that left shifts work regardless of the signedness. vt = TypeInt::INT; } } diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 5343b3d1d7a..7b400f76f18 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1185,6 +1185,73 @@ void Type::dump_stats() { } #endif +//------------------------------category--------------------------------------- +#ifndef PRODUCT +Type::Category Type::category() const { + const TypeTuple* tuple; + switch (base()) { + case Type::Int: + case Type::Long: + case Type::Half: + case Type::NarrowOop: + case Type::NarrowKlass: + case Type::Array: + case Type::VectorA: + case Type::VectorS: + case Type::VectorD: + case Type::VectorX: + case Type::VectorY: + case Type::VectorZ: + case Type::AnyPtr: + case Type::RawPtr: + case Type::OopPtr: + case Type::InstPtr: + case Type::AryPtr: + case Type::MetadataPtr: + case Type::KlassPtr: + case Type::Function: + case Type::Return_Address: + case Type::FloatTop: + case Type::FloatCon: + case Type::FloatBot: + case Type::DoubleTop: + case Type::DoubleCon: + case Type::DoubleBot: + return Category::Data; + case Type::Memory: + return Category::Memory; + case Type::Control: + return Category::Control; + case Type::Top: + case Type::Abio: + case Type::Bottom: + return Category::Other; + case Type::Bad: + case Type::lastype: + return Category::Undef; + case Type::Tuple: + // Recursive case. Return CatMixed if the tuple contains types of + // different categories (e.g. CallStaticJavaNode's type), or the specific + // category if all types are of the same category (e.g. IfNode's type). + tuple = is_tuple(); + if (tuple->cnt() == 0) { + return Category::Undef; + } else { + Category first = tuple->field_at(0)->category(); + for (uint i = 1; i < tuple->cnt(); i++) { + if (tuple->field_at(i)->category() != first) { + return Category::Mixed; + } + } + return first; + } + default: + assert(false, "unmatched base type: all base types must be categorized"); + } + return Category::Undef; +} +#endif + //------------------------------typerr----------------------------------------- void Type::typerr( const Type *t ) const { #ifndef PRODUCT diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index bb22b0b14d1..18473488294 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -394,6 +394,17 @@ class Type { } virtual void dump2( Dict &d, uint depth, outputStream *st ) const; static void dump_stats(); + // Groups of types, for debugging and visualization only. + enum class Category { + Data, + Memory, + Mixed, // Tuples with types of different categories. + Control, + Other, // {Type::Top, Type::Abio, Type::Bottom}. + Undef // {Type::Bad, Type::lastype}, for completeness. + }; + // Return the category of this type. + Category category() const; static const char* str(const Type* t); #endif diff --git a/src/hotspot/share/opto/vector.cpp b/src/hotspot/share/opto/vector.cpp index b1d530cc8b4..283ee46b765 100644 --- a/src/hotspot/share/opto/vector.cpp +++ b/src/hotspot/share/opto/vector.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "ci/ciSymbols.hpp" +#include "gc/shared/barrierSet.hpp" #include "opto/castnode.hpp" #include "opto/graphKit.hpp" #include "opto/phaseX.hpp" @@ -413,15 +414,17 @@ void PhaseVector::expand_vunbox_node(VectorUnboxNode* vec_unbox) { Node* mem = vec_unbox->mem(); Node* ctrl = vec_unbox->in(0); - Node* vec_field_ld = LoadNode::make(gvn, - ctrl, - mem, - vec_adr, - vec_adr->bottom_type()->is_ptr(), - TypeOopPtr::make_from_klass(field->type()->as_klass()), - T_OBJECT, - MemNode::unordered); - vec_field_ld = gvn.transform(vec_field_ld); + Node* vec_field_ld; + { + DecoratorSet decorators = MO_UNORDERED | IN_HEAP; + C2AccessValuePtr addr(vec_adr, vec_adr->bottom_type()->is_ptr()); + MergeMemNode* local_mem = MergeMemNode::make(mem); + gvn.record_for_igvn(local_mem); + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + C2OptAccess access(gvn, ctrl, local_mem, decorators, T_OBJECT, obj, addr); + const Type* type = TypeOopPtr::make_from_klass(field->type()->as_klass()); + vec_field_ld = bs->load_at(access, type); + } // For proper aliasing, attach concrete payload type. ciKlass* payload_klass = ciTypeArrayKlass::make(bt); diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index 0979adce7a0..3870d1089f4 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -1225,25 +1225,30 @@ Node* VectorUnboxNode::Ideal(PhaseGVN* phase, bool can_reshape) { ciKlass* vbox_klass = vbox->box_type()->klass(); const TypeVect* in_vt = vbox->vec_type(); const TypeVect* out_vt = type()->is_vect(); - assert(in_vt->length() == out_vt->length(), "mismatch on number of elements"); - Node* value = vbox->in(VectorBoxNode::Value); - - bool is_vector_mask = vbox_klass->is_subclass_of(ciEnv::current()->vector_VectorMask_klass()); - bool is_vector_shuffle = vbox_klass->is_subclass_of(ciEnv::current()->vector_VectorShuffle_klass()); - if (is_vector_mask) { - // VectorUnbox (VectorBox vmask) ==> VectorLoadMask (VectorStoreMask vmask) - value = phase->transform(VectorStoreMaskNode::make(*phase, value, in_vt->element_basic_type(), in_vt->length())); - return new VectorLoadMaskNode(value, out_vt); - } else if (is_vector_shuffle) { - if (is_shuffle_to_vector()) { - // VectorUnbox (VectorBox vshuffle) ==> VectorCastB2X vshuffle - return new VectorCastB2XNode(value, out_vt); + + if (in_vt->length() == out_vt->length()) { + Node* value = vbox->in(VectorBoxNode::Value); + + bool is_vector_mask = vbox_klass->is_subclass_of(ciEnv::current()->vector_VectorMask_klass()); + bool is_vector_shuffle = vbox_klass->is_subclass_of(ciEnv::current()->vector_VectorShuffle_klass()); + if (is_vector_mask) { + // VectorUnbox (VectorBox vmask) ==> VectorLoadMask (VectorStoreMask vmask) + value = phase->transform(VectorStoreMaskNode::make(*phase, value, in_vt->element_basic_type(), in_vt->length())); + return new VectorLoadMaskNode(value, out_vt); + } else if (is_vector_shuffle) { + if (is_shuffle_to_vector()) { + // VectorUnbox (VectorBox vshuffle) ==> VectorCastB2X vshuffle + return new VectorCastB2XNode(value, out_vt); + } else { + // VectorUnbox (VectorBox vshuffle) ==> VectorLoadShuffle vshuffle + return new VectorLoadShuffleNode(value, out_vt); + } } else { - // VectorUnbox (VectorBox vshuffle) ==> VectorLoadShuffle vshuffle - return new VectorLoadShuffleNode(value, out_vt); + // Vector type mismatch is only supported for masks and shuffles, but sometimes it happens in pathological cases. } } else { - assert(false, "type mismatch on vector: %s", vbox_klass->name()->as_utf8()); + // Vector length mismatch. + // Sometimes happen in pathological cases (e.g., when unboxing happens in effectively dead code). } } } diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp index 99bc4147263..fb1e48500e5 100644 --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -29,7 +29,6 @@ #include "ci/ciReplay.hpp" #include "classfile/altHashing.hpp" #include "classfile/classFileStream.hpp" -#include "classfile/classLoader.hpp" #include "classfile/javaClasses.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/javaThreadStatus.hpp" @@ -40,6 +39,7 @@ #include "classfile/vmClasses.hpp" #include "classfile/vmSymbols.hpp" #include "compiler/compiler_globals.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/gcLocker.inline.hpp" #include "interpreter/linkResolver.hpp" #include "jfr/jfrEvents.hpp" diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 6523d4b5d1d..fff02c4d3d9 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -3356,10 +3356,14 @@ JVM_END JVM_ENTRY(jobject, JVM_LatestUserDefinedLoader(JNIEnv *env)) for (vframeStream vfst(thread); !vfst.at_end(); vfst.next()) { - vfst.skip_reflection_related_frames(); // Only needed for 1.4 reflection - oop loader = vfst.method()->method_holder()->class_loader(); + InstanceKlass* ik = vfst.method()->method_holder(); + oop loader = ik->class_loader(); if (loader != NULL && !SystemDictionary::is_platform_class_loader(loader)) { - return JNIHandles::make_local(THREAD, loader); + // Skip reflection related frames + if (!ik->is_subclass_of(vmClasses::reflect_MethodAccessorImpl_klass()) && + !ik->is_subclass_of(vmClasses::reflect_ConstructorAccessorImpl_klass())) { + return JNIHandles::make_local(THREAD, loader); + } } } return NULL; diff --git a/src/hotspot/share/prims/jvmtiEnter.xsl b/src/hotspot/share/prims/jvmtiEnter.xsl index fb2a8e93a21..48d1b58a465 100644 --- a/src/hotspot/share/prims/jvmtiEnter.xsl +++ b/src/hotspot/share/prims/jvmtiEnter.xsl @@ -48,6 +48,7 @@ # include "prims/jvmtiRawMonitor.hpp" # include "prims/jvmtiUtil.hpp" # include "runtime/fieldDescriptor.inline.hpp" +# include "runtime/jniHandles.hpp" # include "runtime/threadSMR.hpp" diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index 1a85d8826af..cb6cb748de3 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -30,6 +30,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmClasses.hpp" #include "classfile/vmSymbols.hpp" +#include "gc/shared/collectedHeap.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/interpreter.hpp" #include "jfr/jfrEvents.hpp" diff --git a/src/hotspot/share/prims/jvmtiEnvBase.hpp b/src/hotspot/share/prims/jvmtiEnvBase.hpp index fa516fe568a..68399ed6a14 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.hpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ #ifndef SHARE_PRIMS_JVMTIENVBASE_HPP #define SHARE_PRIMS_JVMTIENVBASE_HPP -#include "classfile/classLoader.hpp" #include "prims/jvmtiEnvThreadState.hpp" #include "prims/jvmtiEventController.hpp" #include "prims/jvmtiThreadState.hpp" diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp index c2bb3d589b4..eca6c573888 100644 --- a/src/hotspot/share/prims/jvmtiExport.cpp +++ b/src/hotspot/share/prims/jvmtiExport.cpp @@ -1506,6 +1506,9 @@ void JvmtiExport::post_resource_exhausted(jint resource_exhausted_flags, const c JavaThread *thread = JavaThread::current(); + log_error(jvmti)("Posting Resource Exhausted event: %s", + description != nullptr ? description : "unknown"); + // JDK-8213834: handlers of ResourceExhausted may attempt some analysis // which often requires running java. // This will cause problems on threads not able to run java, e.g. compiler diff --git a/src/hotspot/share/prims/jvmtiImpl.cpp b/src/hotspot/share/prims/jvmtiImpl.cpp index c9c25397caa..7f6192f1517 100644 --- a/src/hotspot/share/prims/jvmtiImpl.cpp +++ b/src/hotspot/share/prims/jvmtiImpl.cpp @@ -34,6 +34,7 @@ #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" +#include "oops/klass.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/oopHandle.inline.hpp" #include "prims/jvmtiAgentThread.hpp" @@ -45,6 +46,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/os.hpp" #include "runtime/serviceThread.hpp" #include "runtime/signature.hpp" diff --git a/src/hotspot/share/prims/jvmtiTagMap.cpp b/src/hotspot/share/prims/jvmtiTagMap.cpp index e0ca6e7b249..082f4aa5ec4 100644 --- a/src/hotspot/share/prims/jvmtiTagMap.cpp +++ b/src/hotspot/share/prims/jvmtiTagMap.cpp @@ -28,6 +28,7 @@ #include "classfile/symbolTable.hpp" #include "classfile/vmClasses.hpp" #include "classfile/vmSymbols.hpp" +#include "gc/shared/collectedHeap.hpp" #include "jvmtifiles/jvmtiEnv.hpp" #include "logging/log.hpp" #include "memory/allocation.inline.hpp" diff --git a/src/hotspot/share/prims/jvmtiTagMapTable.cpp b/src/hotspot/share/prims/jvmtiTagMapTable.cpp index 90879a63cd9..6bfca137102 100644 --- a/src/hotspot/share/prims/jvmtiTagMapTable.cpp +++ b/src/hotspot/share/prims/jvmtiTagMapTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/oopStorage.hpp" #include "jvmtifiles/jvmtiEnv.hpp" #include "logging/log.hpp" diff --git a/src/hotspot/share/prims/stackwalk.cpp b/src/hotspot/share/prims/stackwalk.cpp index a45d564efbd..039058f064e 100644 --- a/src/hotspot/share/prims/stackwalk.cpp +++ b/src/hotspot/share/prims/stackwalk.cpp @@ -41,6 +41,7 @@ #include "runtime/stackWatermarkSet.hpp" #include "runtime/thread.inline.hpp" #include "runtime/vframe.inline.hpp" +#include "utilities/formatBuffer.hpp" #include "utilities/globalDefinitions.hpp" // setup and cleanup actions diff --git a/src/hotspot/share/prims/vectorSupport.cpp b/src/hotspot/share/prims/vectorSupport.cpp index 9a12e986496..4d127997c27 100644 --- a/src/hotspot/share/prims/vectorSupport.cpp +++ b/src/hotspot/share/prims/vectorSupport.cpp @@ -139,7 +139,7 @@ Handle VectorSupport::allocate_vector_payload_helper(InstanceKlass* ik, frame* f int vslot = (i * elem_size) / VMRegImpl::stack_slot_size; int off = (i * elem_size) % VMRegImpl::stack_slot_size; - address elem_addr = reg_map->location(vreg->next(vslot)) + off; + address elem_addr = reg_map->location(vreg, vslot) + off; // assumes little endian element order init_payload_element(arr, is_mask, elem_bt, i, elem_addr); } } else { diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index bdde2e3ba86..21fa18e574a 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -1814,7 +1814,7 @@ WB_ENTRY(jobjectArray, WB_getObjectsViaKlassOopMaps(JNIEnv* env, jobject wb, job return NULL; } instanceHandle ih(THREAD, (instanceOop) aoop); - InstanceKlass* klass = InstanceKlass::cast(aoop->klass()); + InstanceKlass* klass = InstanceKlass::cast(ih->klass()); if (klass->nonstatic_oop_map_count() == 0) { return NULL; } @@ -1826,61 +1826,56 @@ WB_ENTRY(jobjectArray, WB_getObjectsViaKlassOopMaps(JNIEnv* env, jobject wb, job map++; } - objArrayOop result_array = - oopFactory::new_objArray(vmClasses::Object_klass(), oop_count, CHECK_NULL); + objArrayHandle result_array = + oopFactory::new_objArray_handle(vmClasses::Object_klass(), oop_count, CHECK_NULL); map = klass->start_of_nonstatic_oop_maps(); - instanceOop ioop = ih(); int index = 0; while (map < end) { int offset = map->offset(); for (unsigned int j = 0; j < map->count(); j++) { - result_array->obj_at_put(index++, ioop->obj_field(offset)); + result_array->obj_at_put(index++, ih->obj_field(offset)); offset += heapOopSize; } map++; } - return (jobjectArray)JNIHandles::make_local(THREAD, result_array); + return (jobjectArray)JNIHandles::make_local(THREAD, result_array()); WB_END class CollectOops : public BasicOopIterateClosure { public: GrowableArray* array; - objArrayOop create_results(TRAPS) { - objArrayOop result_array = - oopFactory::new_objArray(vmClasses::Object_klass(), array->length(), CHECK_NULL); + jobjectArray create_jni_result(JNIEnv* env, TRAPS) { + objArrayHandle result_array = + oopFactory::new_objArray_handle(vmClasses::Object_klass(), array->length(), CHECK_NULL); for (int i = 0 ; i < array->length(); i++) { result_array->obj_at_put(i, array->at(i)()); } - return result_array; - } - - jobjectArray create_jni_result(JNIEnv* env, TRAPS) { - return (jobjectArray)JNIHandles::make_local(THREAD, create_results(THREAD)); + return (jobjectArray)JNIHandles::make_local(THREAD, result_array()); } void add_oop(oop o) { + Handle oh = Handle(Thread::current(), o); // Value might be oop, but JLS can't see as Object, just iterate through it... - if (o != NULL && o->is_inline_type()) { - o->oop_iterate(this); + if (oh != NULL && oh->is_inline_type()) { + oh->oop_iterate(this); } else { - array->append(Handle(Thread::current(), o)); + array->append(oh); } } - void do_oop(oop* o) { add_oop(*o); } - void do_oop(narrowOop* v) { add_oop(CompressedOops::decode(*v)); } + void do_oop(oop* o) { add_oop(HeapAccess<>::oop_load(o)); } + void do_oop(narrowOop* v) { add_oop(HeapAccess<>::oop_load(v)); } }; WB_ENTRY(jobjectArray, WB_getObjectsViaOopIterator(JNIEnv* env, jobject wb, jobject thing)) - ResourceMark rm(THREAD); + ResourceMark rm(thread); + Handle objh(thread, JNIHandles::resolve(thing)); GrowableArray* array = new GrowableArray(128); CollectOops collectOops; collectOops.array = array; - - JNIHandles::resolve(thing)->oop_iterate(&collectOops); - + objh->oop_iterate(&collectOops); return collectOops.create_jni_result(env, THREAD); WB_END diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 670eeddfc95..25327b0fa80 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -34,6 +34,7 @@ #include "code/pcDesc.hpp" #include "code/scopeDesc.hpp" #include "compiler/compilationPolicy.hpp" +#include "gc/shared/collectedHeap.hpp" #include "interpreter/bytecode.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/oopMapCache.hpp" @@ -1331,10 +1332,6 @@ int compare(ReassignedField* left, ReassignedField* right) { // Restore fields of an eliminated instance object using the same field order // returned by HotSpotResolvedObjectTypeImpl.getInstanceFields(true) static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap* reg_map, ObjectValue* sv, int svIndex, oop obj, bool skip_internal, int base_offset, TRAPS) { - if (svIndex >= sv->field_size()) { - // No fields left to re-assign. - return svIndex; - } GrowableArray* fields = new GrowableArray(); InstanceKlass* ik = klass; while (ik != NULL) { @@ -1344,13 +1341,12 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap field._offset = fs.offset(); field._type = Signature::basic_type(fs.signature()); if (field._type == T_INLINE_TYPE) { - field._type = T_OBJECT; - } - if (fs.is_inlined()) { - // Resolve klass of flattened inline type field - Klass* vk = klass->get_inline_type_field_klass(fs.index()); - field._klass = InlineKlass::cast(vk); - field._type = T_INLINE_TYPE; + if (fs.is_inlined()) { + // Resolve klass of flattened inline type field + field._klass = InlineKlass::cast(klass->get_inline_type_field_klass(fs.index())); + } else { + field._type = T_OBJECT; + } } fields->append(field); } @@ -1359,11 +1355,20 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap } fields->sort(compare); for (int i = 0; i < fields->length(); i++) { + BasicType type = fields->at(i)._type; + int offset = base_offset + fields->at(i)._offset; + // Check for flattened inline type field before accessing the ScopeValue because it might not have any fields + if (type == T_INLINE_TYPE) { + // Recursively re-assign flattened inline type fields + InstanceKlass* vk = fields->at(i)._klass; + assert(vk != NULL, "must be resolved"); + offset -= InlineKlass::cast(vk)->first_field_offset(); // Adjust offset to omit oop header + svIndex = reassign_fields_by_klass(vk, fr, reg_map, sv, svIndex, obj, skip_internal, offset, CHECK_0); + continue; // Continue because we don't need to increment svIndex + } intptr_t val; ScopeValue* scope_field = sv->field_at(svIndex); StackValue* value = StackValue::create_stack_value(fr, reg_map, scope_field); - int offset = base_offset + fields->at(i)._offset; - BasicType type = fields->at(i)._type; switch (type) { case T_OBJECT: case T_ARRAY: @@ -1371,15 +1376,6 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap obj->obj_field_put(offset, value->get_obj()()); break; - case T_INLINE_TYPE: { - // Recursively re-assign flattened inline type fields - InstanceKlass* vk = fields->at(i)._klass; - assert(vk != NULL, "must be resolved"); - offset -= InlineKlass::cast(vk)->first_field_offset(); // Adjust offset to omit oop header - svIndex = reassign_fields_by_klass(vk, fr, reg_map, sv, svIndex, obj, skip_internal, offset, CHECK_0); - continue; // Continue because we don't need to increment svIndex - } - // Have to cast to INT (32 bits) pointer to avoid little/big-endian problem. case T_INT: case T_FLOAT: { // 4 bytes. assert(value->type() == T_INT, "Agreement."); @@ -2553,6 +2549,7 @@ Deoptimization::UnrollBlock* Deoptimization::uncommon_trap(JavaThread* thread, j // This enters VM and may safepoint uncommon_trap_inner(thread, trap_request); } + HandleMark hm(thread); return fetch_unroll_info_helper(thread, exec_mode); } diff --git a/src/hotspot/share/runtime/flags/jvmFlagAccess.cpp b/src/hotspot/share/runtime/flags/jvmFlagAccess.cpp index 4695aab8fa4..34c9b949049 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagAccess.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagAccess.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "runtime/flags/jvmFlagAccess.hpp" #include "runtime/flags/jvmFlagLimit.hpp" #include "runtime/flags/jvmFlagConstraintsRuntime.hpp" +#include "runtime/os.hpp" #include "utilities/macros.hpp" #include "utilities/ostream.hpp" diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 16147d41dca..3395ce2c722 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -677,9 +677,6 @@ const intx ObjectAlignmentInBytes = 8; develop(bool, UsePrivilegedStack, true, \ "Enable the security JVM functions") \ \ - develop(bool, ProtectionDomainVerification, true, \ - "Verify protection domain before resolution in system dictionary")\ - \ product(bool, ClassUnloading, true, \ "Do unloading of classes") \ \ diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index bc372c0bcaf..4d22edef1c4 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -25,7 +25,6 @@ #include "precompiled.hpp" #include "jvm.h" #include "aot/aotLoader.hpp" -#include "classfile/classLoader.hpp" #include "classfile/classLoaderDataGraph.hpp" #include "classfile/javaClasses.hpp" #include "classfile/stringTable.hpp" @@ -34,6 +33,7 @@ #include "code/codeCache.hpp" #include "compiler/compileBroker.hpp" #include "compiler/compilerOracle.hpp" +#include "gc/shared/collectedHeap.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "jfr/jfrEvents.hpp" #include "jfr/support/jfrThreadId.hpp" diff --git a/src/hotspot/share/runtime/jniHandles.cpp b/src/hotspot/share/runtime/jniHandles.cpp index 7a0cfbea180..76b15bdc768 100644 --- a/src/hotspot/share/runtime/jniHandles.cpp +++ b/src/hotspot/share/runtime/jniHandles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/vmSymbols.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/oopStorage.inline.hpp" #include "gc/shared/oopStorageSet.hpp" #include "logging/log.hpp" diff --git a/src/hotspot/share/runtime/nonJavaThread.cpp b/src/hotspot/share/runtime/nonJavaThread.cpp new file mode 100644 index 00000000000..7332e59fe0f --- /dev/null +++ b/src/hotspot/share/runtime/nonJavaThread.cpp @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "jvm_io.h" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/gcId.hpp" +#include "runtime/atomic.hpp" +#include "runtime/jniHandles.hpp" +#include "runtime/nonJavaThread.hpp" +#include "runtime/osThread.hpp" +#include "runtime/task.hpp" +#include "runtime/thread.inline.hpp" +#include "utilities/defaultStream.hpp" +#include "utilities/singleWriterSynchronizer.hpp" +#include "utilities/vmError.hpp" + +#if INCLUDE_JFR +#include "jfr/jfr.hpp" +#endif + +// List of all NonJavaThreads and safe iteration over that list. + +class NonJavaThread::List { +public: + NonJavaThread* volatile _head; + SingleWriterSynchronizer _protect; + + List() : _head(NULL), _protect() {} +}; + +NonJavaThread::List NonJavaThread::_the_list; + +NonJavaThread::Iterator::Iterator() : + _protect_enter(_the_list._protect.enter()), + _current(Atomic::load_acquire(&_the_list._head)) +{} + +NonJavaThread::Iterator::~Iterator() { + _the_list._protect.exit(_protect_enter); +} + +void NonJavaThread::Iterator::step() { + assert(!end(), "precondition"); + _current = Atomic::load_acquire(&_current->_next); +} + +NonJavaThread::NonJavaThread() : Thread(), _next(NULL) { + assert(BarrierSet::barrier_set() != NULL, "NonJavaThread created too soon!"); +} + +NonJavaThread::~NonJavaThread() { } + +void NonJavaThread::add_to_the_list() { + MutexLocker ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag); + // Initialize BarrierSet-related data before adding to list. + BarrierSet::barrier_set()->on_thread_attach(this); + Atomic::release_store(&_next, _the_list._head); + Atomic::release_store(&_the_list._head, this); +} + +void NonJavaThread::remove_from_the_list() { + { + MutexLocker ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag); + // Cleanup BarrierSet-related data before removing from list. + BarrierSet::barrier_set()->on_thread_detach(this); + NonJavaThread* volatile* p = &_the_list._head; + for (NonJavaThread* t = *p; t != NULL; p = &t->_next, t = *p) { + if (t == this) { + *p = _next; + break; + } + } + } + // Wait for any in-progress iterators. Concurrent synchronize is not + // allowed, so do it while holding a dedicated lock. Outside and distinct + // from NJTList_lock in case an iteration attempts to lock it. + MutexLocker ml(NonJavaThreadsListSync_lock, Mutex::_no_safepoint_check_flag); + _the_list._protect.synchronize(); + _next = NULL; // Safe to drop the link now. +} + +void NonJavaThread::pre_run() { + add_to_the_list(); + + // This is slightly odd in that NamedThread is a subclass, but + // in fact name() is defined in Thread + assert(this->name() != NULL, "thread name was not set before it was started"); + this->set_native_thread_name(this->name()); +} + +void NonJavaThread::post_run() { + JFR_ONLY(Jfr::on_thread_exit(this);) + remove_from_the_list(); + unregister_thread_stack_with_NMT(); + // Ensure thread-local-storage is cleared before termination. + Thread::clear_thread_current(); + osthread()->set_state(ZOMBIE); +} + +// NamedThread -- non-JavaThread subclasses with multiple +// uniquely named instances should derive from this. +NamedThread::NamedThread() : + NonJavaThread(), + _name(NULL), + _processed_thread(NULL), + _gc_id(GCId::undefined()) +{} + +NamedThread::~NamedThread() { + FREE_C_HEAP_ARRAY(char, _name); +} + +void NamedThread::set_name(const char* format, ...) { + guarantee(_name == NULL, "Only get to set name once."); + _name = NEW_C_HEAP_ARRAY(char, max_name_len, mtThread); + va_list ap; + va_start(ap, format); + jio_vsnprintf(_name, max_name_len, format, ap); + va_end(ap); +} + +void NamedThread::print_on(outputStream* st) const { + st->print("\"%s\" ", name()); + Thread::print_on(st); + st->cr(); +} + + +// ======= WatcherThread ======== + +// The watcher thread exists to simulate timer interrupts. It should +// be replaced by an abstraction over whatever native support for +// timer interrupts exists on the platform. + +WatcherThread* WatcherThread::_watcher_thread = NULL; +bool WatcherThread::_startable = false; +volatile bool WatcherThread::_should_terminate = false; + +WatcherThread::WatcherThread() : NonJavaThread() { + assert(watcher_thread() == NULL, "we can only allocate one WatcherThread"); + if (os::create_thread(this, os::watcher_thread)) { + _watcher_thread = this; + + // Set the watcher thread to the highest OS priority which should not be + // used, unless a Java thread with priority java.lang.Thread.MAX_PRIORITY + // is created. The only normal thread using this priority is the reference + // handler thread, which runs for very short intervals only. + // If the VMThread's priority is not lower than the WatcherThread profiling + // will be inaccurate. + os::set_priority(this, MaxPriority); + os::start_thread(this); + } +} + +int WatcherThread::sleep() const { + // The WatcherThread does not participate in the safepoint protocol + // for the PeriodicTask_lock because it is not a JavaThread. + MonitorLocker ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag); + + if (_should_terminate) { + // check for termination before we do any housekeeping or wait + return 0; // we did not sleep. + } + + // remaining will be zero if there are no tasks, + // causing the WatcherThread to sleep until a task is + // enrolled + int remaining = PeriodicTask::time_to_wait(); + int time_slept = 0; + + // we expect this to timeout - we only ever get unparked when + // we should terminate or when a new task has been enrolled + OSThreadWaitState osts(this->osthread(), false /* not Object.wait() */); + + jlong time_before_loop = os::javaTimeNanos(); + + while (true) { + bool timedout = ml.wait(remaining); + jlong now = os::javaTimeNanos(); + + if (remaining == 0) { + // if we didn't have any tasks we could have waited for a long time + // consider the time_slept zero and reset time_before_loop + time_slept = 0; + time_before_loop = now; + } else { + // need to recalculate since we might have new tasks in _tasks + time_slept = (int) ((now - time_before_loop) / 1000000); + } + + // Change to task list or spurious wakeup of some kind + if (timedout || _should_terminate) { + break; + } + + remaining = PeriodicTask::time_to_wait(); + if (remaining == 0) { + // Last task was just disenrolled so loop around and wait until + // another task gets enrolled + continue; + } + + remaining -= time_slept; + if (remaining <= 0) { + break; + } + } + + return time_slept; +} + +void WatcherThread::run() { + assert(this == watcher_thread(), "just checking"); + + this->set_active_handles(JNIHandleBlock::allocate_block()); + while (true) { + assert(watcher_thread() == Thread::current(), "thread consistency check"); + assert(watcher_thread() == this, "thread consistency check"); + + // Calculate how long it'll be until the next PeriodicTask work + // should be done, and sleep that amount of time. + int time_waited = sleep(); + + if (VMError::is_error_reported()) { + // A fatal error has happened, the error handler(VMError::report_and_die) + // should abort JVM after creating an error log file. However in some + // rare cases, the error handler itself might deadlock. Here periodically + // check for error reporting timeouts, and if it happens, just proceed to + // abort the VM. + + // This code is in WatcherThread because WatcherThread wakes up + // periodically so the fatal error handler doesn't need to do anything; + // also because the WatcherThread is less likely to crash than other + // threads. + + for (;;) { + // Note: we use naked sleep in this loop because we want to avoid using + // any kind of VM infrastructure which may be broken at this point. + if (VMError::check_timeout()) { + // We hit error reporting timeout. Error reporting was interrupted and + // will be wrapping things up now (closing files etc). Give it some more + // time, then quit the VM. + os::naked_short_sleep(200); + // Print a message to stderr. + fdStream err(defaultStream::output_fd()); + err.print_raw_cr("# [ timer expired, abort... ]"); + // skip atexit/vm_exit/vm_abort hooks + os::die(); + } + + // Wait a second, then recheck for timeout. + os::naked_short_sleep(999); + } + } + + if (_should_terminate) { + // check for termination before posting the next tick + break; + } + + PeriodicTask::real_time_tick(time_waited); + } + + // Signal that it is terminated + { + MutexLocker mu(Terminator_lock, Mutex::_no_safepoint_check_flag); + _watcher_thread = NULL; + Terminator_lock->notify_all(); + } +} + +void WatcherThread::start() { + assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required"); + + if (watcher_thread() == NULL && _startable) { + _should_terminate = false; + // Create the single instance of WatcherThread + new WatcherThread(); + } +} + +void WatcherThread::make_startable() { + assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required"); + _startable = true; +} + +void WatcherThread::stop() { + { + // Follow normal safepoint aware lock enter protocol since the + // WatcherThread is stopped by another JavaThread. + MutexLocker ml(PeriodicTask_lock); + _should_terminate = true; + + WatcherThread* watcher = watcher_thread(); + if (watcher != NULL) { + // unpark the WatcherThread so it can see that it should terminate + watcher->unpark(); + } + } + + MonitorLocker mu(Terminator_lock); + + while (watcher_thread() != NULL) { + // This wait should make safepoint checks, wait without a timeout, + // and wait as a suspend-equivalent condition. + mu.wait(0, Mutex::_as_suspend_equivalent_flag); + } +} + +void WatcherThread::unpark() { + assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required"); + PeriodicTask_lock->notify(); +} + +void WatcherThread::print_on(outputStream* st) const { + st->print("\"%s\" ", name()); + Thread::print_on(st); + st->cr(); +} + diff --git a/src/hotspot/share/runtime/nonJavaThread.hpp b/src/hotspot/share/runtime/nonJavaThread.hpp new file mode 100644 index 00000000000..c35234015a7 --- /dev/null +++ b/src/hotspot/share/runtime/nonJavaThread.hpp @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_RUNTIME_NONJAVATHREAD_HPP +#define SHARE_RUNTIME_NONJAVATHREAD_HPP + +#include "runtime/thread.hpp" + +class NonJavaThread: public Thread { + friend class VMStructs; + + NonJavaThread* volatile _next; + + class List; + static List _the_list; + + void add_to_the_list(); + void remove_from_the_list(); + + protected: + virtual void pre_run(); + virtual void post_run(); + + public: + NonJavaThread(); + ~NonJavaThread(); + + class Iterator; +}; + +// Provides iteration over the list of NonJavaThreads. +// List addition occurs in pre_run(), and removal occurs in post_run(), +// so that only live fully-initialized threads can be found in the list. +// Threads created after an iterator is constructed will not be visited +// by the iterator. The scope of an iterator is a critical section; there +// must be no safepoint checks in that scope. +class NonJavaThread::Iterator : public StackObj { + uint _protect_enter; + NonJavaThread* _current; + + NONCOPYABLE(Iterator); + +public: + Iterator(); + ~Iterator(); + + bool end() const { return _current == NULL; } + NonJavaThread* current() const { return _current; } + void step(); +}; + +// Name support for threads. non-JavaThread subclasses with multiple +// uniquely named instances should derive from this. +class NamedThread: public NonJavaThread { + friend class VMStructs; + enum { + max_name_len = 64 + }; + private: + char* _name; + // log Thread being processed by oops_do + Thread* _processed_thread; + uint _gc_id; // The current GC id when a thread takes part in GC + + public: + NamedThread(); + ~NamedThread(); + // May only be called once per thread. + void set_name(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); + virtual bool is_Named_thread() const { return true; } + virtual char* name() const { return _name == NULL ? (char*)"Unknown Thread" : _name; } + Thread *processed_thread() { return _processed_thread; } + void set_processed_thread(Thread *thread) { _processed_thread = thread; } + virtual void print_on(outputStream* st) const; + + void set_gc_id(uint gc_id) { _gc_id = gc_id; } + uint gc_id() { return _gc_id; } +}; + +// Worker threads are named and have an id of an assigned work. +class WorkerThread: public NamedThread { + private: + uint _id; + public: + WorkerThread() : _id(0) { } + virtual bool is_Worker_thread() const { return true; } + + virtual WorkerThread* as_Worker_thread() const { + assert(is_Worker_thread(), "Dubious cast to WorkerThread*?"); + return (WorkerThread*) this; + } + + void set_id(uint work_id) { _id = work_id; } + uint id() const { return _id; } +}; + +// A single WatcherThread is used for simulating timer interrupts. +class WatcherThread: public NonJavaThread { + friend class VMStructs; + protected: + virtual void run(); + + private: + static WatcherThread* _watcher_thread; + + static bool _startable; + // volatile due to at least one lock-free read + volatile static bool _should_terminate; + public: + enum SomeConstants { + delay_interval = 10 // interrupt delay in milliseconds + }; + + // Constructor + WatcherThread(); + + // No destruction allowed + ~WatcherThread() { + guarantee(false, "WatcherThread deletion must fix the race with VM termination"); + } + + // Tester + bool is_Watcher_thread() const { return true; } + + // Printing + char* name() const { return (char*)"VM Periodic Task Thread"; } + void print_on(outputStream* st) const; + void unpark(); + + // Returns the single instance of WatcherThread + static WatcherThread* watcher_thread() { return _watcher_thread; } + + // Create and start the single instance of WatcherThread, or stop it on shutdown + static void start(); + static void stop(); + // Only allow start once the VM is sufficiently initialized + // Otherwise the first task to enroll will trigger the start + static void make_startable(); + private: + int sleep() const; +}; + +#endif // SHARE_RUNTIME_NONJAVATHREAD_HPP diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index c32c7764cf4..44c7cb14b2b 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -24,7 +24,6 @@ #include "precompiled.hpp" #include "jvm.h" -#include "classfile/classLoader.hpp" #include "classfile/javaClasses.hpp" #include "classfile/moduleEntry.hpp" #include "classfile/systemDictionary.hpp" @@ -52,6 +51,7 @@ #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.inline.hpp" #include "runtime/osThread.hpp" @@ -1814,6 +1814,10 @@ void os::print_memory_mappings(outputStream* st) { void os::pretouch_memory(void* start, void* end, size_t page_size) { for (volatile char *p = (char*)start; p < (char*)end; p += page_size) { + // Note: this must be a store, not a load. On many OSes loads from fresh + // memory would be satisfied from a single mapped page containing all zeros. + // We need to store something to each page to get them backed by their own + // memory, which is the effect we want here. *p = 0; } } diff --git a/src/hotspot/share/runtime/reflection.cpp b/src/hotspot/share/runtime/reflection.cpp index 8d8e3de8c5d..6196447ab4b 100644 --- a/src/hotspot/share/runtime/reflection.cpp +++ b/src/hotspot/share/runtime/reflection.cpp @@ -53,6 +53,7 @@ #include "runtime/signature.hpp" #include "runtime/thread.inline.hpp" #include "runtime/vframe.inline.hpp" +#include "utilities/formatBuffer.hpp" #include "utilities/globalDefinitions.hpp" static void trace_class_resolution(oop mirror) { diff --git a/src/hotspot/share/runtime/registerMap.hpp b/src/hotspot/share/runtime/registerMap.hpp index 0ca09d07ce4..c37b3f4c182 100644 --- a/src/hotspot/share/runtime/registerMap.hpp +++ b/src/hotspot/share/runtime/registerMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,6 +99,14 @@ class RegisterMap : public StackObj { } } + address location(VMReg base_reg, int slot_idx) const { + if (slot_idx > 0) { + return pd_location(base_reg, slot_idx); + } else { + return location(base_reg); + } + } + void set_location(VMReg reg, address loc) { int index = reg->value() / location_valid_type_size; assert(0 <= reg->value() && reg->value() < reg_count, "range check"); diff --git a/src/hotspot/share/runtime/safepoint.cpp b/src/hotspot/share/runtime/safepoint.cpp index 9bdb3b27757..988c96ad492 100644 --- a/src/hotspot/share/runtime/safepoint.cpp +++ b/src/hotspot/share/runtime/safepoint.cpp @@ -591,7 +591,7 @@ class ParallelSPCleanupTask : public AbstractGangTask { OopStorage::trigger_cleanup_if_needed(); } - _subtasks.all_tasks_completed(_num_workers); + _subtasks.all_tasks_claimed(); } }; diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 0e82859208f..2abe9f54e3c 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -39,17 +39,18 @@ #include "compiler/compileBroker.hpp" #include "compiler/disassembler.hpp" #include "gc/shared/barrierSet.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/gcLocker.inline.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" #include "jfr/jfrEvents.hpp" #include "logging/log.hpp" -#include "memory/metaspaceShared.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/access.hpp" #include "oops/fieldStreams.inline.hpp" +#include "oops/compiledICHolder.inline.hpp" #include "oops/klass.hpp" #include "oops/method.inline.hpp" #include "oops/objArrayKlass.hpp" diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp index 6487329e3f7..0172da35747 100644 --- a/src/hotspot/share/runtime/stubRoutines.cpp +++ b/src/hotspot/share/runtime/stubRoutines.cpp @@ -487,6 +487,7 @@ address StubRoutines::select_fill_function(BasicType t, bool aligned, const char case T_NARROWOOP: case T_NARROWKLASS: case T_ADDRESS: + case T_VOID: // Currently unsupported return NULL; diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index d0be868d523..bd2fd5ce7b3 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -28,7 +28,6 @@ #include "logging/log.hpp" #include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" -#include "memory/metaspaceShared.hpp" #include "memory/padded.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.hpp" diff --git a/src/hotspot/share/runtime/task.cpp b/src/hotspot/share/runtime/task.cpp index bc019daba57..fa74e8a3a2e 100644 --- a/src/hotspot/share/runtime/task.cpp +++ b/src/hotspot/share/runtime/task.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "memory/allocation.hpp" #include "runtime/init.hpp" +#include "runtime/nonJavaThread.hpp" #include "runtime/task.hpp" #include "runtime/thread.inline.hpp" #include "runtime/timer.hpp" diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index 4ad138e36b4..087d9c1afb5 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -28,7 +28,6 @@ #include "classfile/classLoader.hpp" #include "classfile/javaClasses.hpp" #include "classfile/javaThreadStatus.hpp" -#include "classfile/moduleEntry.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmClasses.hpp" #include "classfile/vmSymbols.hpp" @@ -36,14 +35,15 @@ #include "code/scopeDesc.hpp" #include "compiler/compileBroker.hpp" #include "compiler/compileTask.hpp" +#include "compiler/compilerThread.hpp" #include "gc/shared/barrierSet.hpp" +#include "gc/shared/collectedHeap.hpp" #include "gc/shared/gcId.hpp" #include "gc/shared/gcLocker.inline.hpp" #include "gc/shared/gcVMOperations.hpp" #include "gc/shared/oopStorage.hpp" #include "gc/shared/oopStorageSet.hpp" #include "gc/shared/tlab_globals.hpp" -#include "gc/shared/workgroup.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/linkResolver.hpp" #include "interpreter/oopMapCache.hpp" @@ -90,6 +90,7 @@ #include "runtime/memprofiler.hpp" #include "runtime/monitorDeflationThread.hpp" #include "runtime/mutexLocker.hpp" +#include "runtime/nonJavaThread.hpp" #include "runtime/objectMonitor.hpp" #include "runtime/orderAccess.hpp" #include "runtime/osThread.hpp" @@ -101,8 +102,6 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stackWatermarkSet.hpp" #include "runtime/statSampler.hpp" -#include "runtime/stubRoutines.hpp" -#include "runtime/sweeper.hpp" #include "runtime/task.hpp" #include "runtime/thread.inline.hpp" #include "runtime/threadCritical.hpp" @@ -127,7 +126,6 @@ #include "utilities/events.hpp" #include "utilities/macros.hpp" #include "utilities/preserveException.hpp" -#include "utilities/singleWriterSynchronizer.hpp" #include "utilities/spinYield.hpp" #include "utilities/vmError.hpp" #if INCLUDE_JVMCI @@ -1106,306 +1104,6 @@ void JavaThread::allocate_threadObj(Handle thread_group, const char* thread_name THREAD); } -// List of all NonJavaThreads and safe iteration over that list. - -class NonJavaThread::List { -public: - NonJavaThread* volatile _head; - SingleWriterSynchronizer _protect; - - List() : _head(NULL), _protect() {} -}; - -NonJavaThread::List NonJavaThread::_the_list; - -NonJavaThread::Iterator::Iterator() : - _protect_enter(_the_list._protect.enter()), - _current(Atomic::load_acquire(&_the_list._head)) -{} - -NonJavaThread::Iterator::~Iterator() { - _the_list._protect.exit(_protect_enter); -} - -void NonJavaThread::Iterator::step() { - assert(!end(), "precondition"); - _current = Atomic::load_acquire(&_current->_next); -} - -NonJavaThread::NonJavaThread() : Thread(), _next(NULL) { - assert(BarrierSet::barrier_set() != NULL, "NonJavaThread created too soon!"); -} - -NonJavaThread::~NonJavaThread() { } - -void NonJavaThread::add_to_the_list() { - MutexLocker ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag); - // Initialize BarrierSet-related data before adding to list. - BarrierSet::barrier_set()->on_thread_attach(this); - Atomic::release_store(&_next, _the_list._head); - Atomic::release_store(&_the_list._head, this); -} - -void NonJavaThread::remove_from_the_list() { - { - MutexLocker ml(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag); - // Cleanup BarrierSet-related data before removing from list. - BarrierSet::barrier_set()->on_thread_detach(this); - NonJavaThread* volatile* p = &_the_list._head; - for (NonJavaThread* t = *p; t != NULL; p = &t->_next, t = *p) { - if (t == this) { - *p = _next; - break; - } - } - } - // Wait for any in-progress iterators. Concurrent synchronize is not - // allowed, so do it while holding a dedicated lock. Outside and distinct - // from NJTList_lock in case an iteration attempts to lock it. - MutexLocker ml(NonJavaThreadsListSync_lock, Mutex::_no_safepoint_check_flag); - _the_list._protect.synchronize(); - _next = NULL; // Safe to drop the link now. -} - -void NonJavaThread::pre_run() { - add_to_the_list(); - - // This is slightly odd in that NamedThread is a subclass, but - // in fact name() is defined in Thread - assert(this->name() != NULL, "thread name was not set before it was started"); - this->set_native_thread_name(this->name()); -} - -void NonJavaThread::post_run() { - JFR_ONLY(Jfr::on_thread_exit(this);) - remove_from_the_list(); - unregister_thread_stack_with_NMT(); - // Ensure thread-local-storage is cleared before termination. - Thread::clear_thread_current(); - osthread()->set_state(ZOMBIE); -} - -// NamedThread -- non-JavaThread subclasses with multiple -// uniquely named instances should derive from this. -NamedThread::NamedThread() : - NonJavaThread(), - _name(NULL), - _processed_thread(NULL), - _gc_id(GCId::undefined()) -{} - -NamedThread::~NamedThread() { - FREE_C_HEAP_ARRAY(char, _name); -} - -void NamedThread::set_name(const char* format, ...) { - guarantee(_name == NULL, "Only get to set name once."); - _name = NEW_C_HEAP_ARRAY(char, max_name_len, mtThread); - va_list ap; - va_start(ap, format); - jio_vsnprintf(_name, max_name_len, format, ap); - va_end(ap); -} - -void NamedThread::print_on(outputStream* st) const { - st->print("\"%s\" ", name()); - Thread::print_on(st); - st->cr(); -} - - -// ======= WatcherThread ======== - -// The watcher thread exists to simulate timer interrupts. It should -// be replaced by an abstraction over whatever native support for -// timer interrupts exists on the platform. - -WatcherThread* WatcherThread::_watcher_thread = NULL; -bool WatcherThread::_startable = false; -volatile bool WatcherThread::_should_terminate = false; - -WatcherThread::WatcherThread() : NonJavaThread() { - assert(watcher_thread() == NULL, "we can only allocate one WatcherThread"); - if (os::create_thread(this, os::watcher_thread)) { - _watcher_thread = this; - - // Set the watcher thread to the highest OS priority which should not be - // used, unless a Java thread with priority java.lang.Thread.MAX_PRIORITY - // is created. The only normal thread using this priority is the reference - // handler thread, which runs for very short intervals only. - // If the VMThread's priority is not lower than the WatcherThread profiling - // will be inaccurate. - os::set_priority(this, MaxPriority); - os::start_thread(this); - } -} - -int WatcherThread::sleep() const { - // The WatcherThread does not participate in the safepoint protocol - // for the PeriodicTask_lock because it is not a JavaThread. - MonitorLocker ml(PeriodicTask_lock, Mutex::_no_safepoint_check_flag); - - if (_should_terminate) { - // check for termination before we do any housekeeping or wait - return 0; // we did not sleep. - } - - // remaining will be zero if there are no tasks, - // causing the WatcherThread to sleep until a task is - // enrolled - int remaining = PeriodicTask::time_to_wait(); - int time_slept = 0; - - // we expect this to timeout - we only ever get unparked when - // we should terminate or when a new task has been enrolled - OSThreadWaitState osts(this->osthread(), false /* not Object.wait() */); - - jlong time_before_loop = os::javaTimeNanos(); - - while (true) { - bool timedout = ml.wait(remaining); - jlong now = os::javaTimeNanos(); - - if (remaining == 0) { - // if we didn't have any tasks we could have waited for a long time - // consider the time_slept zero and reset time_before_loop - time_slept = 0; - time_before_loop = now; - } else { - // need to recalculate since we might have new tasks in _tasks - time_slept = (int) ((now - time_before_loop) / 1000000); - } - - // Change to task list or spurious wakeup of some kind - if (timedout || _should_terminate) { - break; - } - - remaining = PeriodicTask::time_to_wait(); - if (remaining == 0) { - // Last task was just disenrolled so loop around and wait until - // another task gets enrolled - continue; - } - - remaining -= time_slept; - if (remaining <= 0) { - break; - } - } - - return time_slept; -} - -void WatcherThread::run() { - assert(this == watcher_thread(), "just checking"); - - this->set_active_handles(JNIHandleBlock::allocate_block()); - while (true) { - assert(watcher_thread() == Thread::current(), "thread consistency check"); - assert(watcher_thread() == this, "thread consistency check"); - - // Calculate how long it'll be until the next PeriodicTask work - // should be done, and sleep that amount of time. - int time_waited = sleep(); - - if (VMError::is_error_reported()) { - // A fatal error has happened, the error handler(VMError::report_and_die) - // should abort JVM after creating an error log file. However in some - // rare cases, the error handler itself might deadlock. Here periodically - // check for error reporting timeouts, and if it happens, just proceed to - // abort the VM. - - // This code is in WatcherThread because WatcherThread wakes up - // periodically so the fatal error handler doesn't need to do anything; - // also because the WatcherThread is less likely to crash than other - // threads. - - for (;;) { - // Note: we use naked sleep in this loop because we want to avoid using - // any kind of VM infrastructure which may be broken at this point. - if (VMError::check_timeout()) { - // We hit error reporting timeout. Error reporting was interrupted and - // will be wrapping things up now (closing files etc). Give it some more - // time, then quit the VM. - os::naked_short_sleep(200); - // Print a message to stderr. - fdStream err(defaultStream::output_fd()); - err.print_raw_cr("# [ timer expired, abort... ]"); - // skip atexit/vm_exit/vm_abort hooks - os::die(); - } - - // Wait a second, then recheck for timeout. - os::naked_short_sleep(999); - } - } - - if (_should_terminate) { - // check for termination before posting the next tick - break; - } - - PeriodicTask::real_time_tick(time_waited); - } - - // Signal that it is terminated - { - MutexLocker mu(Terminator_lock, Mutex::_no_safepoint_check_flag); - _watcher_thread = NULL; - Terminator_lock->notify_all(); - } -} - -void WatcherThread::start() { - assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required"); - - if (watcher_thread() == NULL && _startable) { - _should_terminate = false; - // Create the single instance of WatcherThread - new WatcherThread(); - } -} - -void WatcherThread::make_startable() { - assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required"); - _startable = true; -} - -void WatcherThread::stop() { - { - // Follow normal safepoint aware lock enter protocol since the - // WatcherThread is stopped by another JavaThread. - MutexLocker ml(PeriodicTask_lock); - _should_terminate = true; - - WatcherThread* watcher = watcher_thread(); - if (watcher != NULL) { - // unpark the WatcherThread so it can see that it should terminate - watcher->unpark(); - } - } - - MonitorLocker mu(Terminator_lock); - - while (watcher_thread() != NULL) { - // This wait should make safepoint checks, wait without a timeout, - // and wait as a suspend-equivalent condition. - mu.wait(0, Mutex::_as_suspend_equivalent_flag); - } -} - -void WatcherThread::unpark() { - assert(PeriodicTask_lock->owned_by_self(), "PeriodicTask_lock required"); - PeriodicTask_lock->notify(); -} - -void WatcherThread::print_on(outputStream* st) const { - st->print("\"%s\" ", name()); - Thread::print_on(st); - st->cr(); -} - // ======= JavaThread ======== #if INCLUDE_JVMCI @@ -1674,19 +1372,14 @@ void JavaThread::block_if_vm_exited() { } } - -// Remove this ifdef when C1 is ported to the compiler interface. -static void compiler_thread_entry(JavaThread* thread, TRAPS); -static void sweeper_thread_entry(JavaThread* thread, TRAPS); - JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) : JavaThread() { _jni_attach_state = _not_attaching_via_jni; set_entry_point(entry_point); // Create the native thread itself. // %note runtime_23 os::ThreadType thr_type = os::java_thread; - thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread : - os::java_thread; + thr_type = entry_point == &CompilerThread::thread_entry ? os::compiler_thread : + os::java_thread; os::create_thread(this, thr_type, stack_sz); // The _osthread may be NULL here because we ran out of memory (too many threads active). // We need to throw and OutOfMemoryError - however we cannot do this here because the caller @@ -3139,70 +2832,6 @@ bool JavaThread::sleep(jlong millis) { } } -static void compiler_thread_entry(JavaThread* thread, TRAPS) { - assert(thread->is_Compiler_thread(), "must be compiler thread"); - CompileBroker::compiler_thread_loop(); -} - -static void sweeper_thread_entry(JavaThread* thread, TRAPS) { - NMethodSweeper::sweeper_loop(); -} - -// Create a CompilerThread -CompilerThread::CompilerThread(CompileQueue* queue, - CompilerCounters* counters) - : JavaThread(&compiler_thread_entry) { - _env = NULL; - _log = NULL; - _task = NULL; - _queue = queue; - _counters = counters; - _buffer_blob = NULL; - _compiler = NULL; - - // Compiler uses resource area for compilation, let's bias it to mtCompiler - resource_area()->bias_to(mtCompiler); - -#ifndef PRODUCT - _ideal_graph_printer = NULL; -#endif -} - -CompilerThread::~CompilerThread() { - // Delete objects which were allocated on heap. - delete _counters; -} - -bool CompilerThread::can_call_java() const { - return _compiler != NULL && _compiler->is_jvmci(); -} - -// Create sweeper thread -CodeCacheSweeperThread::CodeCacheSweeperThread() -: JavaThread(&sweeper_thread_entry) { - _scanned_compiled_method = NULL; -} - -void CodeCacheSweeperThread::oops_do_no_frames(OopClosure* f, CodeBlobClosure* cf) { - JavaThread::oops_do_no_frames(f, cf); - if (_scanned_compiled_method != NULL && cf != NULL) { - // Safepoints can occur when the sweeper is scanning an nmethod so - // process it here to make sure it isn't unloaded in the middle of - // a scan. - cf->do_code_blob(_scanned_compiled_method); - } -} - -void CodeCacheSweeperThread::nmethods_do(CodeBlobClosure* cf) { - JavaThread::nmethods_do(cf); - if (_scanned_compiled_method != NULL && cf != NULL) { - // Safepoints can occur when the sweeper is scanning an nmethod so - // process it here to make sure it isn't unloaded in the middle of - // a scan. - cf->do_code_blob(_scanned_compiled_method); - } -} - // ======= Threads ======== @@ -3733,6 +3362,10 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { #if INCLUDE_CDS // capture the module path info from the ModuleEntryTable ClassLoader::initialize_module_path(THREAD); + if (HAS_PENDING_EXCEPTION) { + java_lang_Throwable::print(PENDING_EXCEPTION, tty); + vm_exit_during_initialization("ClassLoader::initialize_module_path() failed unexpectedly"); + } #endif #if INCLUDE_JVMCI diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index 265a0cf644a..51614ded8ce 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -35,7 +35,6 @@ #include "runtime/globals.hpp" #include "runtime/handshake.hpp" #include "runtime/javaFrameAnchor.hpp" -#include "runtime/jniHandles.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" #include "runtime/park.hpp" @@ -60,6 +59,7 @@ class ThreadSafepointState; class ThreadsList; class ThreadsSMRSupport; +class JNIHandleBlock; class JvmtiRawMonitor; class JvmtiSampledObjectAllocEventCollector; class JvmtiThreadState; @@ -69,15 +69,6 @@ class ThreadStatistics; class ConcurrentLocksDump; class MonitorInfo; -class BufferBlob; -class AbstractCompiler; -class ciEnv; -class CompileThread; -class CompileLog; -class CompileTask; -class CompileQueue; -class CompilerCounters; - class vframeArray; class vframe; class javaVFrame; @@ -87,10 +78,6 @@ class JvmtiDeferredUpdates; class ThreadClosure; class ICRefillVerifier; -class IdealGraphPrinter; - -class JVMCIEnv; -class JVMCIPrimitiveArray; class Metadata; class ResourceArea; @@ -287,12 +274,6 @@ class Thread: public ThreadShadow { // suspend/resume lock: used for self-suspend Monitor* _SR_lock; - // Stack watermark barriers. - StackWatermarks _stack_watermarks; - - public: - inline StackWatermarks* stack_watermarks() { return &_stack_watermarks; } - protected: enum SuspendFlags { // NOTE: avoid using the sign-bit as cc generates different test code @@ -865,141 +846,6 @@ inline Thread* Thread::current_or_null_safe() { return NULL; } -class NonJavaThread: public Thread { - friend class VMStructs; - - NonJavaThread* volatile _next; - - class List; - static List _the_list; - - void add_to_the_list(); - void remove_from_the_list(); - - protected: - virtual void pre_run(); - virtual void post_run(); - - public: - NonJavaThread(); - ~NonJavaThread(); - - class Iterator; -}; - -// Provides iteration over the list of NonJavaThreads. -// List addition occurs in pre_run(), and removal occurs in post_run(), -// so that only live fully-initialized threads can be found in the list. -// Threads created after an iterator is constructed will not be visited -// by the iterator. The scope of an iterator is a critical section; there -// must be no safepoint checks in that scope. -class NonJavaThread::Iterator : public StackObj { - uint _protect_enter; - NonJavaThread* _current; - - NONCOPYABLE(Iterator); - -public: - Iterator(); - ~Iterator(); - - bool end() const { return _current == NULL; } - NonJavaThread* current() const { return _current; } - void step(); -}; - -// Name support for threads. non-JavaThread subclasses with multiple -// uniquely named instances should derive from this. -class NamedThread: public NonJavaThread { - friend class VMStructs; - enum { - max_name_len = 64 - }; - private: - char* _name; - // log Thread being processed by oops_do - Thread* _processed_thread; - uint _gc_id; // The current GC id when a thread takes part in GC - - public: - NamedThread(); - ~NamedThread(); - // May only be called once per thread. - void set_name(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); - virtual bool is_Named_thread() const { return true; } - virtual char* name() const { return _name == NULL ? (char*)"Unknown Thread" : _name; } - Thread *processed_thread() { return _processed_thread; } - void set_processed_thread(Thread *thread) { _processed_thread = thread; } - virtual void print_on(outputStream* st) const; - - void set_gc_id(uint gc_id) { _gc_id = gc_id; } - uint gc_id() { return _gc_id; } -}; - -// Worker threads are named and have an id of an assigned work. -class WorkerThread: public NamedThread { - private: - uint _id; - public: - WorkerThread() : _id(0) { } - virtual bool is_Worker_thread() const { return true; } - - virtual WorkerThread* as_Worker_thread() const { - assert(is_Worker_thread(), "Dubious cast to WorkerThread*?"); - return (WorkerThread*) this; - } - - void set_id(uint work_id) { _id = work_id; } - uint id() const { return _id; } -}; - -// A single WatcherThread is used for simulating timer interrupts. -class WatcherThread: public NonJavaThread { - friend class VMStructs; - protected: - virtual void run(); - - private: - static WatcherThread* _watcher_thread; - - static bool _startable; - // volatile due to at least one lock-free read - volatile static bool _should_terminate; - public: - enum SomeConstants { - delay_interval = 10 // interrupt delay in milliseconds - }; - - // Constructor - WatcherThread(); - - // No destruction allowed - ~WatcherThread() { - guarantee(false, "WatcherThread deletion must fix the race with VM termination"); - } - - // Tester - bool is_Watcher_thread() const { return true; } - - // Printing - char* name() const { return (char*)"VM Periodic Task Thread"; } - void print_on(outputStream* st) const; - void unpark(); - - // Returns the single instance of WatcherThread - static WatcherThread* watcher_thread() { return _watcher_thread; } - - // Create and start the single instance of WatcherThread, or stop it on shutdown - static void start(); - static void stop(); - // Only allow start once the VM is sufficiently initialized - // Otherwise the first task to enroll will trigger the start - static void make_startable(); - private: - int sleep() const; -}; - - class CompilerThread; typedef void (*ThreadFunction)(JavaThread*, TRAPS); @@ -1212,6 +1058,11 @@ class JavaThread: public Thread { friend class ThreadWaitTransition; friend class VM_Exit; + // Stack watermark barriers. + StackWatermarks _stack_watermarks; + + public: + inline StackWatermarks* stack_watermarks() { return &_stack_watermarks; } public: // Constructor @@ -1904,100 +1755,6 @@ inline JavaThread* JavaThread::current() { return Thread::current()->as_Java_thread(); } -inline CompilerThread* JavaThread::as_CompilerThread() { - assert(is_Compiler_thread(), "just checking"); - return (CompilerThread*)this; -} - -// Dedicated thread to sweep the code cache -class CodeCacheSweeperThread : public JavaThread { - CompiledMethod* _scanned_compiled_method; // nmethod being scanned by the sweeper - public: - CodeCacheSweeperThread(); - // Track the nmethod currently being scanned by the sweeper - void set_scanned_compiled_method(CompiledMethod* cm) { - assert(_scanned_compiled_method == NULL || cm == NULL, "should reset to NULL before writing a new value"); - _scanned_compiled_method = cm; - } - - // Hide sweeper thread from external view. - bool is_hidden_from_external_view() const { return true; } - - bool is_Code_cache_sweeper_thread() const { return true; } - - // Prevent GC from unloading _scanned_compiled_method - void oops_do_no_frames(OopClosure* f, CodeBlobClosure* cf); - void nmethods_do(CodeBlobClosure* cf); -}; - -// A thread used for Compilation. -class CompilerThread : public JavaThread { - friend class VMStructs; - private: - CompilerCounters* _counters; - - ciEnv* _env; - CompileLog* _log; - CompileTask* volatile _task; // print_threads_compiling can read this concurrently. - CompileQueue* _queue; - BufferBlob* _buffer_blob; - - AbstractCompiler* _compiler; - TimeStamp _idle_time; - - public: - - static CompilerThread* current(); - - CompilerThread(CompileQueue* queue, CompilerCounters* counters); - ~CompilerThread(); - - bool is_Compiler_thread() const { return true; } - - virtual bool can_call_java() const; - - // Hide native compiler threads from external view. - bool is_hidden_from_external_view() const { return !can_call_java(); } - - void set_compiler(AbstractCompiler* c) { _compiler = c; } - AbstractCompiler* compiler() const { return _compiler; } - - CompileQueue* queue() const { return _queue; } - CompilerCounters* counters() const { return _counters; } - - // Get/set the thread's compilation environment. - ciEnv* env() { return _env; } - void set_env(ciEnv* env) { _env = env; } - - BufferBlob* get_buffer_blob() const { return _buffer_blob; } - void set_buffer_blob(BufferBlob* b) { _buffer_blob = b; } - - // Get/set the thread's logging information - CompileLog* log() { return _log; } - void init_log(CompileLog* log) { - // Set once, for good. - assert(_log == NULL, "set only once"); - _log = log; - } - - void start_idle_timer() { _idle_time.update(); } - jlong idle_time_millis() { - return TimeHelper::counter_to_millis(_idle_time.ticks_since_update()); - } - -#ifndef PRODUCT - private: - IdealGraphPrinter *_ideal_graph_printer; - public: - IdealGraphPrinter *ideal_graph_printer() { return _ideal_graph_printer; } - void set_ideal_graph_printer(IdealGraphPrinter *n) { _ideal_graph_printer = n; } -#endif - - // Get/set the thread's current task - CompileTask* task() { return _task; } - void set_task(CompileTask* task) { _task = task; } -}; - inline JavaThread* Thread::as_Java_thread() { assert(is_Java_thread(), "incorrect cast to JavaThread"); return static_cast(this); @@ -2008,10 +1765,6 @@ inline const JavaThread* Thread::as_Java_thread() const { return static_cast(this); } -inline CompilerThread* CompilerThread::current() { - return JavaThread::current()->as_CompilerThread(); -} - // The active thread queue. It also keeps track of the current used // thread priorities. class Threads: AllStatic { diff --git a/src/hotspot/share/runtime/vframe.cpp b/src/hotspot/share/runtime/vframe.cpp index 5fa4e13e11a..9cd129c65d1 100644 --- a/src/hotspot/share/runtime/vframe.cpp +++ b/src/hotspot/share/runtime/vframe.cpp @@ -562,15 +562,6 @@ void vframeStreamCommon::skip_prefixed_method_and_wrappers() { } } - -void vframeStreamCommon::skip_reflection_related_frames() { - while (!at_end() && - (method()->method_holder()->is_subclass_of(vmClasses::reflect_MethodAccessorImpl_klass()) || - method()->method_holder()->is_subclass_of(vmClasses::reflect_ConstructorAccessorImpl_klass()))) { - next(); - } -} - javaVFrame* vframeStreamCommon::asJavaVFrame() { javaVFrame* result = NULL; if (_mode == compiled_mode) { diff --git a/src/hotspot/share/runtime/vframe.hpp b/src/hotspot/share/runtime/vframe.hpp index 52e58403094..487d064d3ff 100644 --- a/src/hotspot/share/runtime/vframe.hpp +++ b/src/hotspot/share/runtime/vframe.hpp @@ -328,10 +328,6 @@ class vframeStreamCommon : StackObj { // Implements security traversal. Skips depth no. of frame including // special security frames and prefixed native methods void security_get_caller_frame(int depth); - - // Helper routine for JVM_LatestUserDefinedLoader -- needed for 1.4 - // reflection implementation - void skip_reflection_related_frames(); }; class vframeStream : public vframeStreamCommon { diff --git a/src/hotspot/share/runtime/vmOperations.cpp b/src/hotspot/share/runtime/vmOperations.cpp index a2ea0dec51d..f92cf522e79 100644 --- a/src/hotspot/share/runtime/vmOperations.cpp +++ b/src/hotspot/share/runtime/vmOperations.cpp @@ -41,6 +41,7 @@ #include "runtime/deoptimization.hpp" #include "runtime/frame.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/synchronizer.hpp" #include "runtime/thread.inline.hpp" #include "runtime/threadSMR.inline.hpp" diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index cbf8c2ad912..94752fe01e5 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -89,6 +89,7 @@ #include "runtime/globals.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/monitorDeflationThread.hpp" #include "runtime/notificationThread.hpp" #include "runtime/os.hpp" @@ -260,7 +261,7 @@ typedef HashtableEntry KlassHashtableEntry; nonstatic_field(Klass, _java_mirror, OopHandle) \ nonstatic_field(Klass, _modifier_flags, jint) \ nonstatic_field(Klass, _super, Klass*) \ - volatile_nonstatic_field(Klass, _subklass, Klass*) \ + volatile_nonstatic_field(Klass, _subklass, Klass*) \ nonstatic_field(Klass, _layout_helper, jint) \ nonstatic_field(Klass, _name, Symbol*) \ nonstatic_field(Klass, _access_flags, AccessFlags) \ diff --git a/src/hotspot/share/runtime/vmThread.cpp b/src/hotspot/share/runtime/vmThread.cpp index 9f7988aa6e7..d4285da0a95 100644 --- a/src/hotspot/share/runtime/vmThread.cpp +++ b/src/hotspot/share/runtime/vmThread.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "compiler/compileBroker.hpp" +#include "gc/shared/collectedHeap.hpp" #include "jfr/jfrEvents.hpp" #include "jfr/support/jfrThreadId.hpp" #include "logging/log.hpp" @@ -36,6 +37,7 @@ #include "runtime/atomic.hpp" #include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" #include "runtime/perfData.hpp" diff --git a/src/hotspot/share/runtime/vmThread.hpp b/src/hotspot/share/runtime/vmThread.hpp index b0928a5b28b..915f8926e29 100644 --- a/src/hotspot/share/runtime/vmThread.hpp +++ b/src/hotspot/share/runtime/vmThread.hpp @@ -26,6 +26,7 @@ #define SHARE_RUNTIME_VMTHREAD_HPP #include "runtime/perfDataTypes.hpp" +#include "runtime/nonJavaThread.hpp" #include "runtime/thread.hpp" #include "runtime/task.hpp" #include "runtime/vmOperations.hpp" diff --git a/src/hotspot/share/services/attachListener.hpp b/src/hotspot/share/services/attachListener.hpp index 251b9766735..d80f2be9511 100644 --- a/src/hotspot/share/services/attachListener.hpp +++ b/src/hotspot/share/services/attachListener.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "memory/allocation.hpp" #include "runtime/atomic.hpp" +#include "runtime/globals.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index 8bdca49d57b..68b0ce08514 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -44,6 +44,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/jniHandles.hpp" #include "runtime/os.hpp" #include "runtime/vm_version.hpp" #include "services/diagnosticArgument.hpp" diff --git a/src/hotspot/share/services/management.cpp b/src/hotspot/share/services/management.cpp index b62874f999e..9070f26bc01 100644 --- a/src/hotspot/share/services/management.cpp +++ b/src/hotspot/share/services/management.cpp @@ -28,6 +28,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmClasses.hpp" #include "compiler/compileBroker.hpp" +#include "gc/shared/collectedHeap.hpp" #include "memory/allocation.inline.hpp" #include "memory/iterator.hpp" #include "memory/oopFactory.hpp" diff --git a/src/hotspot/share/services/memReporter.hpp b/src/hotspot/share/services/memReporter.hpp index 6685c102efc..70e73e5d97c 100644 --- a/src/hotspot/share/services/memReporter.hpp +++ b/src/hotspot/share/services/memReporter.hpp @@ -39,14 +39,17 @@ */ class MemReporterBase : public StackObj { private: - size_t _scale; // report in this scale - outputStream* _output; // destination + const size_t _scale; // report in this scale + outputStream* const _output; // destination public: - MemReporterBase(outputStream* out = NULL, size_t scale = K) - : _scale(scale) { - _output = (out == NULL) ? tty : out; - } + + // Default scale to use if no scale given. + static const size_t default_scale = K; + + MemReporterBase(outputStream* out, size_t scale = default_scale) : + _scale(scale), _output(out) + {} protected: inline outputStream* output() const { @@ -74,7 +77,6 @@ class MemReporterBase : public StackObj { size_t reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) const; size_t committed_total(const MallocMemory* malloc, const VirtualMemory* vm) const; - // Print summary total, malloc and virtual memory void print_total(size_t reserved, size_t committed) const; void print_malloc(size_t amount, size_t count, MEMFLAGS flag = mtNone) const; @@ -100,7 +102,7 @@ class MemSummaryReporter : public MemReporterBase { public: // This constructor is for normal reporting from a recent baseline. MemSummaryReporter(MemBaseline& baseline, outputStream* output, - size_t scale = K) : MemReporterBase(output, scale), + size_t scale = default_scale) : MemReporterBase(output, scale), _malloc_snapshot(baseline.malloc_memory_snapshot()), _vm_snapshot(baseline.virtual_memory_snapshot()), _instance_class_count(baseline.instance_class_count()), @@ -125,7 +127,7 @@ class MemDetailReporter : public MemSummaryReporter { MemBaseline& _baseline; public: - MemDetailReporter(MemBaseline& baseline, outputStream* output, size_t scale = K) : + MemDetailReporter(MemBaseline& baseline, outputStream* output, size_t scale = default_scale) : MemSummaryReporter(baseline, output, scale), _baseline(baseline) { } @@ -162,7 +164,7 @@ class MemSummaryDiffReporter : public MemReporterBase { public: MemSummaryDiffReporter(MemBaseline& early_baseline, MemBaseline& current_baseline, - outputStream* output, size_t scale = K) : MemReporterBase(output, scale), + outputStream* output, size_t scale = default_scale) : MemReporterBase(output, scale), _early_baseline(early_baseline), _current_baseline(current_baseline) { assert(early_baseline.baseline_type() != MemBaseline::Not_baselined, "Not baselined"); assert(current_baseline.baseline_type() != MemBaseline::Not_baselined, "Not baselined"); @@ -201,7 +203,7 @@ class MemSummaryDiffReporter : public MemReporterBase { class MemDetailDiffReporter : public MemSummaryDiffReporter { public: MemDetailDiffReporter(MemBaseline& early_baseline, MemBaseline& current_baseline, - outputStream* output, size_t scale = K) : + outputStream* output, size_t scale = default_scale) : MemSummaryDiffReporter(early_baseline, current_baseline, output, scale) { } // Generate detail comparison report diff --git a/src/hotspot/share/services/memTracker.cpp b/src/hotspot/share/services/memTracker.cpp index 8470f530c69..1791e21602f 100644 --- a/src/hotspot/share/services/memTracker.cpp +++ b/src/hotspot/share/services/memTracker.cpp @@ -170,7 +170,14 @@ bool MemTracker::transition_to(NMT_TrackingLevel level) { return true; } +// Report during error reporting. +void MemTracker::error_report(outputStream* output) { + if (tracking_level() >= NMT_summary) { + report(true, output, MemReporterBase::default_scale); // just print summary for error case. + } +} +// Report when handling PrintNMTStatistics before VM shutdown. static volatile bool g_final_report_did_run = false; void MemTracker::final_report(outputStream* output) { // This function is called during both error reporting and normal VM exit. @@ -181,25 +188,25 @@ void MemTracker::final_report(outputStream* output) { if (Atomic::cmpxchg(&g_final_report_did_run, false, true) == false) { NMT_TrackingLevel level = tracking_level(); if (level >= NMT_summary) { - report(level == NMT_summary, output); + report(level == NMT_summary, output, 1); } } } -void MemTracker::report(bool summary_only, outputStream* output) { +void MemTracker::report(bool summary_only, outputStream* output, size_t scale) { assert(output != NULL, "No output stream"); MemBaseline baseline; if (baseline.baseline(summary_only)) { if (summary_only) { - MemSummaryReporter rpt(baseline, output); + MemSummaryReporter rpt(baseline, output, scale); rpt.report(); } else { - MemDetailReporter rpt(baseline, output); + MemDetailReporter rpt(baseline, output, scale); rpt.report(); output->print("Metaspace:"); // The basic metaspace report avoids any locking and should be safe to // be called at any time. - MetaspaceUtils::print_basic_report(output, K); + MetaspaceUtils::print_basic_report(output, scale); } } } @@ -260,7 +267,7 @@ class StatisticsWalker : public MallocSiteWalker { _stack_depth_distribution[frames - 1] ++; // hash distribution - int hash_bucket = e->hash() % MallocSiteTable::hash_buckets(); + int hash_bucket = ((unsigned)e->hash()) % MallocSiteTable::hash_buckets(); if (_current_hash_bucket == -1) { _current_hash_bucket = hash_bucket; _current_bucket_length = 1; diff --git a/src/hotspot/share/services/memTracker.hpp b/src/hotspot/share/services/memTracker.hpp index 7097144c242..1e7b394dc82 100644 --- a/src/hotspot/share/services/memTracker.hpp +++ b/src/hotspot/share/services/memTracker.hpp @@ -286,13 +286,10 @@ class MemTracker : AllStatic { return NMTQuery_lock; } - // Make a final report or report for hs_err file. - static void error_report(outputStream* output) { - if (tracking_level() >= NMT_summary) { - report(true, output); // just print summary for error case. - } - } + // Report during error reporting. + static void error_report(outputStream* output); + // Report when handling PrintNMTStatistics before VM shutdown. static void final_report(outputStream* output); // Stored baseline @@ -308,7 +305,7 @@ class MemTracker : AllStatic { private: static NMT_TrackingLevel init_tracking_level(); - static void report(bool summary_only, outputStream* output); + static void report(bool summary_only, outputStream* output, size_t scale); private: // Tracking level diff --git a/src/hotspot/share/services/runtimeService.cpp b/src/hotspot/share/services/runtimeService.cpp index be2108a86c7..d2e8d058a98 100644 --- a/src/hotspot/share/services/runtimeService.cpp +++ b/src/hotspot/share/services/runtimeService.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,6 @@ */ #include "precompiled.hpp" -#include "classfile/classLoader.hpp" #include "logging/log.hpp" #include "logging/logStream.hpp" #include "runtime/vm_version.hpp" diff --git a/src/hotspot/share/services/threadService.cpp b/src/hotspot/share/services/threadService.cpp index ee08ac41606..c0476bba8f2 100644 --- a/src/hotspot/share/services/threadService.cpp +++ b/src/hotspot/share/services/threadService.cpp @@ -33,6 +33,7 @@ #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/instanceKlass.hpp" +#include "oops/klass.inline.hpp" #include "oops/objArrayKlass.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/oop.inline.hpp" diff --git a/src/hotspot/share/services/threadService.hpp b/src/hotspot/share/services/threadService.hpp index 470bead25a6..6784fbc5c03 100644 --- a/src/hotspot/share/services/threadService.hpp +++ b/src/hotspot/share/services/threadService.hpp @@ -30,7 +30,6 @@ #include "classfile/javaThreadStatus.hpp" #include "runtime/handles.hpp" #include "runtime/init.hpp" -#include "runtime/jniHandles.hpp" #include "runtime/objectMonitor.hpp" #include "runtime/perfData.hpp" #include "runtime/safepoint.hpp" diff --git a/src/hotspot/share/utilities/nativeCallStack.cpp b/src/hotspot/share/utilities/nativeCallStack.cpp index 45a29424fd7..b03d3dfcf46 100644 --- a/src/hotspot/share/utilities/nativeCallStack.cpp +++ b/src/hotspot/share/utilities/nativeCallStack.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,14 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/nativeCallStack.hpp" +static unsigned int calculate_hash(address stack[NMT_TrackingStackDepth]) { + uintptr_t hash = 0; + for (int i = 0; i < NMT_TrackingStackDepth; i++) { + hash += (uintptr_t)stack[i]; + } + return hash; +} + NativeCallStack::NativeCallStack(int toSkip, bool fillStack) : _hash_value(0) { @@ -51,6 +59,7 @@ NativeCallStack::NativeCallStack(int toSkip, bool fillStack) : _stack[index] = NULL; } } + _hash_value = calculate_hash(_stack); } NativeCallStack::NativeCallStack(address* pc, int frameCount) { @@ -63,7 +72,7 @@ NativeCallStack::NativeCallStack(address* pc, int frameCount) { for (; index < NMT_TrackingStackDepth; index ++) { _stack[index] = NULL; } - _hash_value = 0; + _hash_value = calculate_hash(_stack); } // number of stack frames captured @@ -77,21 +86,6 @@ int NativeCallStack::frames() const { return index; } -// Hash code. Any better algorithm? -unsigned int NativeCallStack::hash() const { - uintptr_t hash_val = _hash_value; - if (hash_val == 0) { - for (int index = 0; index < NMT_TrackingStackDepth; index++) { - if (_stack[index] == NULL) break; - hash_val += (uintptr_t)_stack[index]; - } - - NativeCallStack* p = const_cast(this); - p->_hash_value = (unsigned int)(hash_val & 0xFFFFFFFF); - } - return _hash_value; -} - void NativeCallStack::print_on(outputStream* out) const { print_on(out, 0); } diff --git a/src/hotspot/share/utilities/nativeCallStack.hpp b/src/hotspot/share/utilities/nativeCallStack.hpp index 724bba8ed35..090b0530a56 100644 --- a/src/hotspot/share/utilities/nativeCallStack.hpp +++ b/src/hotspot/share/utilities/nativeCallStack.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,8 +91,7 @@ class NativeCallStack : public StackObj { return _stack[index]; } - // Hash code. Any better algorithm? - unsigned int hash() const; + unsigned int hash() const { return _hash_value; } void print_on(outputStream* out) const; void print_on(outputStream* out, int indent) const; diff --git a/src/hotspot/share/utilities/ostream.cpp b/src/hotspot/share/utilities/ostream.cpp index 148390e93da..61ff92be830 100644 --- a/src/hotspot/share/utilities/ostream.cpp +++ b/src/hotspot/share/utilities/ostream.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ #include "runtime/arguments.hpp" #include "runtime/os.inline.hpp" #include "runtime/orderAccess.hpp" +#include "runtime/safepoint.hpp" #include "runtime/vm_version.hpp" #include "utilities/defaultStream.hpp" #include "utilities/macros.hpp" diff --git a/src/java.base/macosx/native/libjava/java_props_macosx.c b/src/java.base/macosx/native/libjava/java_props_macosx.c index 321f7583b26..2189c1f94e3 100644 --- a/src/java.base/macosx/native/libjava/java_props_macosx.c +++ b/src/java.base/macosx/native/libjava/java_props_macosx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -247,15 +247,35 @@ void setOSNameAndVersion(java_props_t *sprops) { [invoke getReturnValue:&osVer]; NSString *nsVerStr; - if (osVer.patchVersion == 0) { // Omit trailing ".0" - nsVerStr = [NSString stringWithFormat:@"%ld.%ld", - (long)osVer.majorVersion, (long)osVer.minorVersion]; + // Copy out the char* if running on version other than 10.16 Mac OS (10.16 == 11.x) + // or explicitly requesting version compatibility + if (!((long)osVer.majorVersion == 10 && (long)osVer.minorVersion >= 16) || + (getenv("SYSTEM_VERSION_COMPAT") != NULL)) { + if (osVer.patchVersion == 0) { // Omit trailing ".0" + nsVerStr = [NSString stringWithFormat:@"%ld.%ld", + (long)osVer.majorVersion, (long)osVer.minorVersion]; + } else { + nsVerStr = [NSString stringWithFormat:@"%ld.%ld.%ld", + (long)osVer.majorVersion, (long)osVer.minorVersion, (long)osVer.patchVersion]; + } + // Copy out the char* + osVersionCStr = strdup([nsVerStr UTF8String]); } else { - nsVerStr = [NSString stringWithFormat:@"%ld.%ld.%ld", - (long)osVer.majorVersion, (long)osVer.minorVersion, (long)osVer.patchVersion]; + // Version 10.16, without explicit env setting of SYSTEM_VERSION_COMPAT + // AKA 11.x; compute the version number from the letter in the ProductBuildVersion + NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile : + @"/System/Library/CoreServices/SystemVersion.plist"]; + if (version != NULL) { + NSString *nsBuildVerStr = [version objectForKey : @"ProductBuildVersion"]; + if (nsBuildVerStr != NULL && nsBuildVerStr.length >= 3) { + int letter = [nsBuildVerStr characterAtIndex:2]; + if (letter >= 'B' && letter <= 'Z') { + int vers = letter - 'A' - 1; + asprintf(&osVersionCStr, "11.%d", vers); + } + } + } } - // Copy out the char* - osVersionCStr = strdup([nsVerStr UTF8String]); } // Fallback if running on pre-10.9 Mac OS if (osVersionCStr == NULL) { diff --git a/src/java.base/share/classes/java/io/ObjectInputStream.java b/src/java.base/share/classes/java/io/ObjectInputStream.java index 03d3aa8dc45..931a829df73 100644 --- a/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,7 @@ import static java.io.ObjectStreamClass.processQueue; import jdk.internal.access.SharedSecrets; +import jdk.internal.event.DeserializationEvent; import jdk.internal.misc.Unsafe; import sun.reflect.misc.ReflectUtil; import sun.security.action.GetBooleanAction; @@ -1323,9 +1324,12 @@ public final void setObjectInputFilter(ObjectInputFilter filter) { } /** - * Invoke the serialization filter if non-null. + * Invokes the serialization filter if non-null. + * * If the filter rejects or an exception is thrown, throws InvalidClassException. * + * Logs and/or commits a {@code DeserializationEvent}, if configured. + * * @param clazz the class; may be null * @param arrayLength the array length requested; use {@code -1} if not creating an array * @throws InvalidClassException if it rejected by the filter or @@ -1333,11 +1337,12 @@ public final void setObjectInputFilter(ObjectInputFilter filter) { */ private void filterCheck(Class clazz, int arrayLength) throws InvalidClassException { + // Info about the stream is not available if overridden by subclass, return 0 + long bytesRead = (bin == null) ? 0 : bin.getBytesRead(); + RuntimeException ex = null; + ObjectInputFilter.Status status = null; + if (serialFilter != null) { - RuntimeException ex = null; - ObjectInputFilter.Status status; - // Info about the stream is not available if overridden by subclass, return 0 - long bytesRead = (bin == null) ? 0 : bin.getBytesRead(); try { status = serialFilter.checkInput(new FilterValues(clazz, arrayLength, totalObjectRefs, depth, bytesRead)); @@ -1355,12 +1360,24 @@ private void filterCheck(Class clazz, int arrayLength) status, clazz, arrayLength, totalObjectRefs, depth, bytesRead, Objects.toString(ex, "n/a")); } - if (status == null || - status == ObjectInputFilter.Status.REJECTED) { - InvalidClassException ice = new InvalidClassException("filter status: " + status); - ice.initCause(ex); - throw ice; - } + } + DeserializationEvent event = new DeserializationEvent(); + if (event.shouldCommit()) { + event.filterConfigured = serialFilter != null; + event.filterStatus = status != null ? status.name() : null; + event.type = clazz; + event.arrayLength = arrayLength; + event.objectReferences = totalObjectRefs; + event.depth = depth; + event.bytesRead = bytesRead; + event.exceptionType = ex != null ? ex.getClass() : null; + event.exceptionMessage = ex != null ? ex.getMessage() : null; + event.commit(); + } + if (serialFilter != null && (status == null || status == ObjectInputFilter.Status.REJECTED)) { + InvalidClassException ice = new InvalidClassException("filter status: " + status); + ice.initCause(ex); + throw ice; } } diff --git a/src/java.base/share/classes/java/lang/Class.java b/src/java.base/share/classes/java/lang/Class.java index 7f02390015a..c37335a987c 100644 --- a/src/java.base/share/classes/java/lang/Class.java +++ b/src/java.base/share/classes/java/lang/Class.java @@ -3221,15 +3221,19 @@ private static void checkPackageAccessForPermittedSubclasses(SecurityManager sm, } /** - * Add a package name prefix if the name is not absolute Remove leading "/" + * Add a package name prefix if the name is not absolute. Remove leading "/" * if name is absolute */ private String resolveName(String name) { if (!name.startsWith("/")) { - Class c = isArray() ? elementType() : this; - String baseName = c.getPackageName(); + String baseName = getPackageName(); if (baseName != null && !baseName.isEmpty()) { - name = baseName.replace('.', '/') + "/" + name; + int len = baseName.length() + 1 + name.length(); + StringBuilder sb = new StringBuilder(len); + name = sb.append(baseName.replace('.', '/')) + .append('/') + .append(name) + .toString(); } } else { name = name.substring(1); diff --git a/src/java.base/share/classes/java/lang/Math.java b/src/java.base/share/classes/java/lang/Math.java index ff7ceff6cf2..bc7d92c98e2 100644 --- a/src/java.base/share/classes/java/lang/Math.java +++ b/src/java.base/share/classes/java/lang/Math.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ * square root, and trigonometric functions. * *

Unlike some of the numeric methods of class - * {@code StrictMath}, all implementations of the equivalent + * {@link java.lang.StrictMath StrictMath}, all implementations of the equivalent * functions of class {@code Math} are not defined to return the * bit-for-bit same results. This relaxation permits * better-performing implementations where strict reproducibility is @@ -99,6 +99,28 @@ * occurs only with a specific minimum or maximum value and * should be checked against the minimum or maximum as appropriate. * + *

IEEE 754 Recommended + * Operations

+ * + * The 2019 revision of the IEEE 754 floating-point standard includes + * a section of recommended operations and the semantics of those + * operations if they are included in a programming environment. The + * recommended operations present in this class include {@link sin + * sin}, {@link cos cos}, {@link tan tan}, {@link asin asin}, {@link + * acos acos}, {@link atan atan}, {@link exp exp}, {@link expm1 + * expm1}, {@link log log}, {@link log10 log10}, {@link log1p log1p}, + * {@link sinh sinh}, {@link cosh cosh}, {@link tanh tanh}, {@link + * hypot hypot}, and {@link pow pow}. (The {@link sqrt sqrt} + * operation is a required part of IEEE 754 from a different section + * of the standard.) The special case behavior of the recommended + * operations generally follows the guidance of the IEEE 754 + * standard. However, the {@code pow} method defines different + * behavior for some arguments, as noted in its {@linkplain pow + * specification}. The IEEE 754 standard defines its operations to be + * correctly rounded, which is a more stringent quality of + * implementation condition than required for most of the methods in + * question that are also included in this class. + * * @author Joseph D. Darcy * @since 1.0 */ @@ -156,7 +178,9 @@ public static double sin(double a) { /** * Returns the trigonometric cosine of an angle. Special cases: *
  • If the argument is NaN or an infinity, then the - * result is NaN.
+ * result is NaN. + *
  • If the argument is zero, then the result is {@code 1.0}. + * * *

    The computed result must be within 1 ulp of the exact result. * Results must be semi-monotonic. @@ -209,7 +233,9 @@ public static double asin(double a) { * Returns the arc cosine of a value; the returned angle is in the * range 0.0 through pi. Special case: *

    • If the argument is NaN or its absolute value is greater - * than 1, then the result is NaN.
    + * than 1, then the result is NaN. + *
  • If the argument is {@code 1.0}, the result is positive zero. + * * *

    The computed result must be within 1 ulp of the exact result. * Results must be semi-monotonic. @@ -226,7 +252,11 @@ public static double acos(double a) { * range -pi/2 through pi/2. Special cases: *

    • If the argument is NaN, then the result is NaN. *
    • If the argument is zero, then the result is a zero with the - * same sign as the argument.
    + * same sign as the argument. + *
  • If the argument is {@linkplain Double#isInfinite infinite}, + * then the result is the closest value to pi/2 with the + * same sign as the input. + * * *

    The computed result must be within 1 ulp of the exact result. * Results must be semi-monotonic. @@ -275,7 +305,9 @@ public static double toDegrees(double angrad) { *

  • If the argument is positive infinity, then the result is * positive infinity. *
  • If the argument is negative infinity, then the result is - * positive zero. + * positive zero. + *
  • If the argument is zero, then the result is {@code 1.0}. + * * *

    The computed result must be within 1 ulp of the exact result. * Results must be semi-monotonic. @@ -297,7 +329,10 @@ public static double exp(double a) { *

  • If the argument is positive infinity, then the result is * positive infinity. *
  • If the argument is positive zero or negative zero, then the - * result is negative infinity. + * result is negative infinity. + *
  • If the argument is {@code 1.0}, then the result is positive + * zero. + * * *

    The computed result must be within 1 ulp of the exact result. * Results must be semi-monotonic. @@ -321,8 +356,10 @@ public static double log(double a) { * positive infinity. *

  • If the argument is positive zero or negative zero, then the * result is negative infinity. - *
  • If the argument is equal to 10n for - * integer n, then the result is n. + *
  • If the argument is equal to 10n for + * integer n, then the result is n. In particular, + * if the argument is {@code 1.0} (100), then the + * result is positive zero. * * *

    The computed result must be within 1 ulp of the exact result. @@ -529,6 +566,15 @@ public static double rint(double a) { *

    The computed result must be within 2 ulps of the exact result. * Results must be semi-monotonic. * + * @apiNote + * For y with a positive sign and finite nonzero + * x, the exact mathematical value of {@code atan2} is + * equal to: + *

      + *
    • If x {@literal >} 0, atan(abs(y/x)) + *
    • If x {@literal <} 0, π - atan(abs(y/x)) + *
    + * * @param y the ordinate coordinate * @param x the abscissa coordinate * @return the theta component of the point @@ -660,6 +706,16 @@ public static double atan2(double y, double x) { *

    The computed result must be within 1 ulp of the exact result. * Results must be semi-monotonic. * + * @apiNote + * The special cases definitions of this method differ from the + * special case definitions of the IEEE 754 recommended {@code + * pow} operation for ±{@code 1.0} raised to an infinite + * power. This method treats such cases as indeterminate and + * specifies a NaN is returned. The IEEE 754 specification treats + * the infinite power as a large integer (large-magnitude + * floating-point numbers are numerically integers, specifically + * even integers) and therefore specifies {@code 1.0} be returned. + * * @param a the base. * @param b the exponent. * @return the value {@code a}{@code b}. @@ -2113,6 +2169,7 @@ public static double tanh(double x) { *

  • If either argument is NaN and neither argument is infinite, * then the result is NaN. * + *
  • If both arguments are zero, the result is positive zero. * * *

    The computed result must be within 1 ulp of the exact diff --git a/src/java.base/share/classes/java/lang/ModuleLayer.java b/src/java.base/share/classes/java/lang/ModuleLayer.java index 5658873c79f..f74146d74d1 100644 --- a/src/java.base/share/classes/java/lang/ModuleLayer.java +++ b/src/java.base/share/classes/java/lang/ModuleLayer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -931,7 +931,9 @@ ServicesCatalog getServicesCatalog() { servicesCatalog = this.servicesCatalog; if (servicesCatalog == null) { servicesCatalog = ServicesCatalog.create(); - nameToModule.values().forEach(servicesCatalog::register); + for (Module m : nameToModule.values()) { + servicesCatalog.register(m); + } this.servicesCatalog = servicesCatalog; } } diff --git a/src/java.base/share/classes/java/lang/StrictMath.java b/src/java.base/share/classes/java/lang/StrictMath.java index 941834381be..506324f3346 100644 --- a/src/java.base/share/classes/java/lang/StrictMath.java +++ b/src/java.base/share/classes/java/lang/StrictMath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,6 +74,15 @@ * occurs only with a specific minimum or maximum value and * should be checked against the minimum or maximum as appropriate. * + *

    IEEE 754 Recommended + * Operations

    + * + * The {@link java.lang.Math Math} class discusses how the shared + * quality of implementation criteria for selected {@code Math} and + * {@code StrictMath} methods relate to the IEEE 754 + * recommended operations. + * * @author Joseph D. Darcy * @since 1.3 */ @@ -126,7 +135,9 @@ private StrictMath() {} /** * Returns the trigonometric cosine of an angle. Special cases: *
    • If the argument is NaN or an infinity, then the - * result is NaN.
    + * result is NaN. + *
  • If the argument is zero, then the result is {@code 1.0}. + * * * @param a an angle, in radians. * @return the cosine of the argument. @@ -162,7 +173,9 @@ private StrictMath() {} * Returns the arc cosine of a value; the returned angle is in the * range 0.0 through pi. Special case: *
    • If the argument is NaN or its absolute value is greater - * than 1, then the result is NaN.
    + * than 1, then the result is NaN. + *
  • If the argument is {@code 1.0}, the result is positive zero. + * * * @param a the value whose arc cosine is to be returned. * @return the arc cosine of the argument. @@ -174,7 +187,11 @@ private StrictMath() {} * range -pi/2 through pi/2. Special cases: *
    • If the argument is NaN, then the result is NaN. *
    • If the argument is zero, then the result is a zero with the - * same sign as the argument.
    + * same sign as the argument. + *
  • If the argument is {@linkplain Double#isInfinite infinite}, + * then the result is the closest value to pi/2 with the + * same sign as the input. + * * * @param a the value whose arc tangent is to be returned. * @return the arc tangent of the argument. @@ -220,7 +237,9 @@ public static strictfp double toDegrees(double angrad) { *
  • If the argument is positive infinity, then the result is * positive infinity. *
  • If the argument is negative infinity, then the result is - * positive zero. + * positive zero. + *
  • If the argument is zero, then the result is {@code 1.0}. + * * * @param a the exponent to raise e to. * @return the value e{@code a}, @@ -238,7 +257,10 @@ public static double exp(double a) { *
  • If the argument is positive infinity, then the result is * positive infinity. *
  • If the argument is positive zero or negative zero, then the - * result is negative infinity. + * result is negative infinity. + *
  • If the argument is {@code 1.0}, then the result is positive + * zero. + * * * @param a a value * @return the value ln {@code a}, the natural logarithm of @@ -256,8 +278,10 @@ public static double exp(double a) { * positive infinity. *
  • If the argument is positive zero or negative zero, then the * result is negative infinity. - *
  • If the argument is equal to 10n for - * integer n, then the result is n. + *
  • If the argument is equal to 10n for + * integer n, then the result is n. In particular, + * if the argument is {@code 1.0} (100), then the + * result is positive zero. * * * @param a a value @@ -517,6 +541,15 @@ public static double rint(double a) { *
  • If both arguments are negative infinity, then the result is the * {@code double} value closest to -3*pi/4. * + * @apiNote + * For y with a positive sign and finite nonzero + * x, the exact mathematical value of {@code atan2} is + * equal to: + *
      + *
    • If x {@literal >} 0, atan(abs(y/x)) + *
    • If x {@literal <} 0, π - atan(abs(y/x)) + *
    + * * @param y the ordinate coordinate * @param x the abscissa coordinate * @return the theta component of the point @@ -642,6 +675,16 @@ public static double rint(double a) { * method if and only if the result of applying the method to the * value is equal to the value.) * + * @apiNote + * The special cases definitions of this method differ from the + * special case definitions of the IEEE 754 recommended {@code + * pow} operation for ±{@code 1.0} raised to an infinite + * power. This method treats such cases as indeterminate and + * specifies a NaN is returned. The IEEE 754 specification treats + * the infinite power as a large integer (large-magnitude + * floating-point numbers are numerically integers, specifically + * even integers) and therefore specifies {@code 1.0} be returned. + * * @param a base. * @param b the exponent. * @return the value {@code a}{@code b}. @@ -1681,6 +1724,7 @@ public static float signum(float f) { *
  • If either argument is NaN and neither argument is infinite, * then the result is NaN. * + *
  • If both arguments are zero, the result is positive zero. * * * @param x a value diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index 5c175b125dc..5d5316f5f06 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -4397,7 +4397,7 @@ void getBytes(byte[] dst, int dstBegin, byte coder) { */ void getBytes(byte[] dst, int srcPos, int dstBegin, byte coder, int length) { if (coder() == coder) { - System.arraycopy(value, srcPos, dst, dstBegin << coder, length << coder()); + System.arraycopy(value, srcPos << coder, dst, dstBegin << coder, length << coder); } else { // this.coder == LATIN && coder == UTF16 StringLatin1.inflate(value, srcPos, dst, dstBegin, length); } diff --git a/src/java.base/share/classes/java/lang/__inline__.java b/src/java.base/share/classes/java/lang/__primitive__.java similarity index 84% rename from src/java.base/share/classes/java/lang/__inline__.java rename to src/java.base/share/classes/java/lang/__primitive__.java index 5727a362c65..f2d567c3a31 100644 --- a/src/java.base/share/classes/java/lang/__inline__.java +++ b/src/java.base/share/classes/java/lang/__primitive__.java @@ -29,12 +29,12 @@ import static java.lang.annotation.ElementType.*; /** - * A class annotated {@code @__inline__} is an inline class. - * This is a temporary workaround to enable use of inline types - * in editors and IDEs that do not yet understand the 'inline' modifier. - * @since 1.12 + * A class annotated {@code @__primitive__} is a primitive class. + * This is a temporary workaround to enable use of primitive classes + * in editors and IDEs that do not yet understand the 'primitive' modifier. + * @since 1.16 */ @Retention(RetentionPolicy.SOURCE) @Target(value={ElementType.TYPE, ElementType.TYPE_USE}) -public @interface __inline__ { +public @interface __primitive__ { } diff --git a/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java index f05f2b10349..df588feb3bc 100644 --- a/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java +++ b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; -import static java.lang.invoke.GenerateJLIClassesHelper.traceSpeciesType; import static java.lang.invoke.LambdaForm.*; import static java.lang.invoke.MethodHandleNatives.Constants.REF_getStatic; import static java.lang.invoke.MethodHandleNatives.Constants.REF_putStatic; @@ -476,8 +475,10 @@ S loadSpecies(S speciesData) { Class salvage = null; try { salvage = BootLoader.loadClassOrNull(className); - traceSpeciesType(className, salvage); } catch (Error ex) { + // ignore + } finally { + traceSpeciesType(className, salvage); } final Class speciesCode; if (salvage != null) { @@ -488,7 +489,6 @@ S loadSpecies(S speciesData) { // Not pregenerated, generate the class try { speciesCode = generateConcreteSpeciesCode(className, speciesData); - traceSpeciesType(className, salvage); // This operation causes a lot of churn: linkSpeciesDataToCode(speciesData, speciesCode); // This operation commits the relation, but causes little churn: diff --git a/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java b/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java index d339733e880..15be51a7e2f 100644 --- a/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java +++ b/src/java.base/share/classes/java/lang/invoke/GenerateJLIClassesHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package java.lang.invoke; -import jdk.internal.misc.CDS; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; import sun.invoke.util.Wrapper; @@ -39,10 +38,7 @@ import java.util.TreeSet; import java.util.stream.Stream; -import static java.lang.invoke.LambdaForm.basicTypeSignature; -import static java.lang.invoke.LambdaForm.shortenSignature; import static java.lang.invoke.LambdaForm.BasicType.*; -import static java.lang.invoke.MethodHandleStatics.TRACE_RESOLVE; import static java.lang.invoke.MethodTypeForm.*; import static java.lang.invoke.LambdaForm.Kind.*; @@ -51,29 +47,6 @@ * generate classes ahead of time. */ class GenerateJLIClassesHelper { - private static final String LF_RESOLVE = "[LF_RESOLVE]"; - private static final String SPECIES_RESOLVE = "[SPECIES_RESOLVE]"; - - static void traceLambdaForm(String name, MethodType type, Class holder, MemberName resolvedMember) { - if (TRACE_RESOLVE) { - System.out.println(LF_RESOLVE + " " + holder.getName() + " " + name + " " + - shortenSignature(basicTypeSignature(type)) + - (resolvedMember != null ? " (success)" : " (fail)")); - } - if (CDS.isDumpingClassList()) { - CDS.traceLambdaFormInvoker(LF_RESOLVE, holder.getName(), name, shortenSignature(basicTypeSignature(type))); - } - } - - static void traceSpeciesType(String cn, Class salvage) { - if (TRACE_RESOLVE) { - System.out.println(SPECIES_RESOLVE + " " + cn + (salvage != null ? " (salvaged)" : " (generated)")); - } - if (CDS.isDumpingClassList()) { - CDS.traceSpeciesType(SPECIES_RESOLVE, cn); - } - } - // Map from DirectMethodHandle method type name to index to LambdForms static final Map DMH_METHOD_TYPE_MAP = Map.of( @@ -323,7 +296,7 @@ static Map generateHolderClasses(Stream traces) { traces.map(line -> line.split(" ")) .forEach(parts -> { switch (parts[0]) { - case SPECIES_RESOLVE: + case "[SPECIES_RESOLVE]": // Allow for new types of species data classes being resolved here assert parts.length >= 2; if (parts[1].startsWith(BMH_SPECIES_PREFIX)) { @@ -333,7 +306,7 @@ static Map generateHolderClasses(Stream traces) { } } break; - case LF_RESOLVE: + case "[LF_RESOLVE]": assert parts.length > 3; String methodType = parts[3]; if (parts[1].equals(INVOKERS_HOLDER_CLASS_NAME)) { diff --git a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 490042fae64..e3700f0d4fd 100644 --- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,6 @@ import java.util.List; import java.util.stream.Stream; -import static java.lang.invoke.GenerateJLIClassesHelper.traceLambdaForm; import static java.lang.invoke.LambdaForm.BasicType; import static java.lang.invoke.LambdaForm.BasicType.*; import static java.lang.invoke.LambdaForm.*; diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java index 942d3b457e6..f926ddf5116 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,15 @@ package java.lang.invoke; +import jdk.internal.misc.CDS; import jdk.internal.misc.Unsafe; import sun.security.action.GetPropertyAction; import java.util.Properties; +import static java.lang.invoke.LambdaForm.basicTypeSignature; +import static java.lang.invoke.LambdaForm.shortenSignature; + /** * This class consists exclusively of static names internal to the * method handle implementation. @@ -108,6 +112,35 @@ static boolean debugEnabled() { LOG_LF_COMPILATION_FAILURE); } + /** + * If requested, logs the result of resolving the LambdaForm to stdout + * and informs the CDS subsystem about it. + */ + /*non-public*/ + static void traceLambdaForm(String name, MethodType type, Class holder, MemberName resolvedMember) { + if (TRACE_RESOLVE) { + System.out.println("[LF_RESOLVE] " + holder.getName() + " " + name + " " + + shortenSignature(basicTypeSignature(type)) + + (resolvedMember != null ? " (success)" : " (fail)")); + } + if (CDS.isDumpingClassList()) { + CDS.traceLambdaFormInvoker("[LF_RESOLVE]", holder.getName(), name, shortenSignature(basicTypeSignature(type))); + } + } + + /** + * If requested, logs the result of resolving the species type to stdout + * and the CDS subsystem. + */ + /*non-public*/ + static void traceSpeciesType(String cn, Class salvage) { + if (TRACE_RESOLVE) { + System.out.println("[SPECIES_RESOLVE] " + cn + (salvage != null ? " (salvaged)" : " (generated)")); + } + if (CDS.isDumpingClassList()) { + CDS.traceSpeciesType("[SPECIES_RESOLVE]", cn); + } + } // handy shared exception makers (they simplify the common case code) /*non-public*/ static InternalError newInternalError(String message) { diff --git a/src/java.base/share/classes/java/net/DatagramSocket.java b/src/java.base/share/classes/java/net/DatagramSocket.java index e95b5ce9bc8..ffd113ecf21 100644 --- a/src/java.base/share/classes/java/net/DatagramSocket.java +++ b/src/java.base/share/classes/java/net/DatagramSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.nio.channels.DatagramChannel; +import java.nio.channels.MulticastChannel; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Set; @@ -81,11 +82,11 @@ * * * {@link java.net.StandardSocketOptions#SO_SNDBUF SO_SNDBUF} - * The size of the socket send buffer + * The size of the socket send buffer in bytes * * * {@link java.net.StandardSocketOptions#SO_RCVBUF SO_RCVBUF} - * The size of the socket receive buffer + * The size of the socket receive buffer in bytes * * * {@link java.net.StandardSocketOptions#SO_REUSEADDR SO_REUSEADDR} @@ -102,10 +103,142 @@ * * * - * An implementation may also support additional options. In particular an implementation - * may support multicast options which - * can be useful when using a plain {@code DatagramSocket} to send datagrams to a - * multicast group. + *

    In addition, the {@code DatagramSocket} class defines methods to {@linkplain + * #joinGroup(SocketAddress, NetworkInterface) join} and {@linkplain + * #leaveGroup(SocketAddress, NetworkInterface) leave} a multicast group, and + * supports multicast options which + * are useful when {@linkplain #joinGroup(SocketAddress, NetworkInterface) joining}, + * {@linkplain #leaveGroup(SocketAddress, NetworkInterface) leaving}, or sending datagrams + * to a multicast group. + * The following multicast options are supported: + *

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Multicast options
    Option NameDescription
    {@link java.net.StandardSocketOptions#IP_MULTICAST_IF IP_MULTICAST_IF} The network interface for Internet Protocol (IP) multicast datagrams
    {@link java.net.StandardSocketOptions#IP_MULTICAST_TTL + * IP_MULTICAST_TTL} The time-to-live for Internet Protocol (IP) multicast + * datagrams
    {@link java.net.StandardSocketOptions#IP_MULTICAST_LOOP + * IP_MULTICAST_LOOP} Loopback for Internet Protocol (IP) multicast datagrams
    + *
    + * An implementation may also support additional options. + * + * @apiNote Multicasting with DatagramSocket + * + *

    {@link DatagramChannel} implements the {@link MulticastChannel} interface + * and provides an alternative API for sending and receiving multicast datagrams. + * The {@link MulticastChannel} API supports both {@linkplain + * MulticastChannel#join(InetAddress, NetworkInterface) any-source} and + * {@linkplain MulticastChannel#join(InetAddress, NetworkInterface, InetAddress) + * source-specific} multicast. Consider using {@code DatagramChannel} for + * multicasting. + * + *

    {@code DatagramSocket} can be used directly for multicasting. However, + * contrarily to {@link MulticastSocket}, {@code DatagramSocket} doesn't call the + * {@link DatagramSocket#setReuseAddress(boolean)} method to enable the SO_REUSEADDR + * socket option by default. If creating a {@code DatagramSocket} intended to + * later join a multicast group, the caller should consider explicitly enabling + * the SO_REUSEADDR option. + * + *

    An instance of {@code DatagramSocket} can be used to send or + * receive multicast datagram packets. It is not necessary to join a multicast + * group in order to send multicast datagrams. Before sending out multicast + * datagram packets however, the default outgoing interface for sending + * multicast datagram should first be configured using + * {@link #setOption(SocketOption, Object) setOption} and + * {@link StandardSocketOptions#IP_MULTICAST_IF}: + * + *

    {@code
    + *    DatagramSocket sender = new DatagramSocket(new InetSocketAddress(0));
    + *    NetworkInterface outgoingIf = NetworkInterface.getByName("en0");
    + *    sender.setOption(StandardSocketOptions.IP_MULTICAST_IF, outgoingIf);
    + *
    + *    // optionally configure multicast TTL; the TTL defines the scope of a
    + *    // multicast datagram, for example, confining it to host local (0) or
    + *    // link local (1) etc...
    + *    int ttl = ...; // a number betwen 0 and 255
    + *    sender.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl);
    + *
    + *    // send a packet to a multicast group
    + *    byte[] msgBytes = ...;
    + *    InetAddress mcastaddr = InetAddress.getByName("228.5.6.7");
    + *    int port = 6789;
    + *    InetSocketAddress dest = new InetSocketAddress(mcastaddr, port);
    + *    DatagramPacket hi = new DatagramPacket(msgBytes, msgBytes.length, dest);
    + *    sender.send(hi);
    + * }
    + * + *

    An instance of {@code DatagramSocket} can also be used to receive + * multicast datagram packets. A {@code DatagramSocket} that is created + * with the intent of receiving multicast datagrams should be created + * unbound. Before binding the socket, {@link #setReuseAddress(boolean) + * setReuseAddress(true)} should be configured: + * + *

    {@code
    + *    DatagramSocket socket = new DatagramSocket(null); // unbound
    + *    socket.setReuseAddress(true); // set reuse address before binding
    + *    socket.bind(new InetSocketAddress(6789)); // bind
    + *
    + *    // joinGroup 228.5.6.7
    + *    InetAddress mcastaddr = InetAddress.getByName("228.5.6.7");
    + *    InetSocketAddress group = new InetSocketAddress(mcastaddr, 0);
    + *    NetworkInterface netIf = NetworkInterface.getByName("en0");
    + *    socket.joinGroup(group, netIf);
    + *    byte[] msgBytes = new byte[1024]; // up to 1024 bytes
    + *    DatagramPacket packet = new DatagramPacket(msgBytes, msgBytes.length);
    + *    socket.receive(packet);
    + *    ....
    + *    // eventually leave group
    + *    socket.leaveGroup(group, netIf);
    + * }
    + * + *

    Platform dependencies + *

    The multicast implementation is intended to map directly to the native + * multicasting facility. Consequently, the following items should be considered + * when developing an application that receives IP multicast datagrams: + *

      + *
    1. Contrarily to {@link DatagramChannel}, the constructors of {@code DatagramSocket} + * do not allow to specify the {@link ProtocolFamily} of the underlying socket. + * Consequently, the protocol family of the underlying socket may not + * correspond to the protocol family of the multicast groups that + * the {@code DatagramSocket} will attempt to join. + *
      + * There is no guarantee that a {@code DatagramSocket} with an underlying + * socket created in one protocol family can join and receive multicast + * datagrams when the address of the multicast group corresponds to + * another protocol family. For example, it is implementation specific if a + * {@code DatagramSocket} to an IPv6 socket can join an IPv4 multicast group + * and receive multicast datagrams sent to the group. + *
    2. + *
    3. Before joining a multicast group, the {@code DatagramSocket} should be + * bound to the wildcard address. + * If the socket is bound to a specific address, rather than the wildcard address + * then it is implementation specific if multicast datagrams are received + * by the socket. + *
    4. + *
    5. The SO_REUSEADDR option should be enabled prior to binding the socket. + * This is required to allow multiple members of the group to bind to the same address. + *
    6. + *
    * * @author Pavani Diwanji * @see java.net.DatagramPacket @@ -655,14 +788,20 @@ public int getSoTimeout() throws SocketException { * of SO_SNDBUF then it is implementation specific if the * packet is sent or discarded. * + * @apiNote + * If {@code size > 0}, this method is equivalent to calling + * {@link #setOption(SocketOption, Object) + * setOption(StandardSocketOptions.SO_SNDBUF, size)}. + * * @param size the size to which to set the send buffer - * size. This value must be greater than 0. + * size, in bytes. This value must be greater than 0. * * @throws SocketException if there is an error * in the underlying protocol, such as an UDP error. * @throws IllegalArgumentException if the value is 0 or is * negative. * @see #getSendBufferSize() + * @see StandardSocketOptions#SO_SNDBUF * @since 1.2 */ public void setSendBufferSize(int size) throws SocketException { @@ -671,12 +810,17 @@ public void setSendBufferSize(int size) throws SocketException { /** * Get value of the SO_SNDBUF option for this {@code DatagramSocket}, that is the - * buffer size used by the platform for output on this {@code DatagramSocket}. + * buffer size, in bytes, used by the platform for output on this {@code DatagramSocket}. + * + * @apiNote + * This method is equivalent to calling {@link #getOption(SocketOption) + * getOption(StandardSocketOptions.SO_SNDBUF)}. * * @return the value of the SO_SNDBUF option for this {@code DatagramSocket} * @throws SocketException if there is an error in * the underlying protocol, such as an UDP error. * @see #setSendBufferSize + * @see StandardSocketOptions#SO_SNDBUF * @since 1.2 */ public int getSendBufferSize() throws SocketException { @@ -702,14 +846,20 @@ public int getSendBufferSize() throws SocketException { * Note: It is implementation specific if a packet larger * than SO_RCVBUF can be received. * + * @apiNote + * If {@code size > 0}, this method is equivalent to calling + * {@link #setOption(SocketOption, Object) + * setOption(StandardSocketOptions.SO_RCVBUF, size)}. + * * @param size the size to which to set the receive buffer - * size. This value must be greater than 0. + * size, in bytes. This value must be greater than 0. * * @throws SocketException if there is an error in * the underlying protocol, such as an UDP error. * @throws IllegalArgumentException if the value is 0 or is * negative. * @see #getReceiveBufferSize() + * @see StandardSocketOptions#SO_RCVBUF * @since 1.2 */ public void setReceiveBufferSize(int size) throws SocketException { @@ -718,11 +868,16 @@ public void setReceiveBufferSize(int size) throws SocketException { /** * Get value of the SO_RCVBUF option for this {@code DatagramSocket}, that is the - * buffer size used by the platform for input on this {@code DatagramSocket}. + * buffer size, in bytes, used by the platform for input on this {@code DatagramSocket}. + * + * @apiNote + * This method is equivalent to calling {@link #getOption(SocketOption) + * getOption(StandardSocketOptions.SO_RCVBUF)}. * * @return the value of the SO_RCVBUF option for this {@code DatagramSocket} * @throws SocketException if there is an error in the underlying protocol, such as an UDP error. * @see #setReceiveBufferSize(int) + * @see StandardSocketOptions#SO_RCVBUF * @since 1.2 */ public int getReceiveBufferSize() throws SocketException { @@ -753,6 +908,10 @@ public int getReceiveBufferSize() throws SocketException { * disabled after a socket is bound (See {@link #isBound()}) * is not defined. * + * @apiNote + * This method is equivalent to calling {@link #setOption(SocketOption, Object) + * setOption(StandardSocketOptions.SO_REUSEADDR, on)}. + * * @param on whether to enable or disable the * @throws SocketException if an error occurs enabling or * disabling the {@code SO_REUSEADDR} socket option, @@ -762,6 +921,7 @@ public int getReceiveBufferSize() throws SocketException { * @see #bind(SocketAddress) * @see #isBound() * @see #isClosed() + * @see StandardSocketOptions#SO_REUSEADDR */ public void setReuseAddress(boolean on) throws SocketException { delegate().setReuseAddress(on); @@ -770,11 +930,16 @@ public void setReuseAddress(boolean on) throws SocketException { /** * Tests if SO_REUSEADDR is enabled. * + * @apiNote + * This method is equivalent to calling {@link #getOption(SocketOption) + * getOption(StandardSocketOptions.SO_REUSEADDR)}. + * * @return a {@code boolean} indicating whether or not SO_REUSEADDR is enabled. * @throws SocketException if there is an error * in the underlying protocol, such as an UDP error. * @since 1.4 * @see #setReuseAddress(boolean) + * @see StandardSocketOptions#SO_REUSEADDR */ public boolean getReuseAddress() throws SocketException { return delegate().getReuseAddress(); @@ -787,6 +952,10 @@ public boolean getReuseAddress() throws SocketException { * started with implementation specific privileges to enable this option or * send broadcast datagrams. * + * @apiNote + * This method is equivalent to calling {@link #setOption(SocketOption, Object) + * setOption(StandardSocketOptions.SO_BROADCAST, on)}. + * * @param on * whether or not to have broadcast turned on. * @@ -796,6 +965,7 @@ public boolean getReuseAddress() throws SocketException { * * @since 1.4 * @see #getBroadcast() + * @see StandardSocketOptions#SO_BROADCAST */ public void setBroadcast(boolean on) throws SocketException { delegate().setBroadcast(on); @@ -803,11 +973,17 @@ public void setBroadcast(boolean on) throws SocketException { /** * Tests if SO_BROADCAST is enabled. + * + * @apiNote + * This method is equivalent to calling {@link #getOption(SocketOption) + * getOption(StandardSocketOptions.SO_BROADCAST)}. + * * @return a {@code boolean} indicating whether or not SO_BROADCAST is enabled. * @throws SocketException if there is an error * in the underlying protocol, such as an UDP error. * @since 1.4 * @see #setBroadcast(boolean) + * @see StandardSocketOptions#SO_BROADCAST */ public boolean getBroadcast() throws SocketException { return delegate().getBroadcast(); @@ -844,11 +1020,16 @@ public boolean getBroadcast() throws SocketException { * for Internet Protocol v6 {@code tc} is the value that * would be placed into the sin6_flowinfo field of the IP header. * + * @apiNote + * This method is equivalent to calling {@link #setOption(SocketOption, Object) + * setOption(StandardSocketOptions.IP_TOS, tc)}. + * * @param tc an {@code int} value for the bitset. * @throws SocketException if there is an error setting the * traffic class or type-of-service * @since 1.4 * @see #getTrafficClass + * @see StandardSocketOptions#IP_TOS */ public void setTrafficClass(int tc) throws SocketException { delegate().setTrafficClass(tc); @@ -864,11 +1045,16 @@ public void setTrafficClass(int tc) throws SocketException { * set using the {@link #setTrafficClass(int)} method on this * DatagramSocket. * + * @apiNote + * This method is equivalent to calling {@link #getOption(SocketOption) + * getOption(StandardSocketOptions.IP_TOS)}. + * * @return the traffic class or type-of-service already set * @throws SocketException if there is an error obtaining the * traffic class or type-of-service value. * @since 1.4 * @see #setTrafficClass(int) + * @see StandardSocketOptions#IP_TOS */ public int getTrafficClass() throws SocketException { return delegate().getTrafficClass(); @@ -946,7 +1132,18 @@ public DatagramChannel getChannel() { * @see java.net.DatagramSocketImplFactory#createDatagramSocketImpl() * @see SecurityManager#checkSetFactory * @since 1.3 + * + * @deprecated Use {@link DatagramChannel}, or subclass {@code DatagramSocket} + * directly. + *
    This method provided a way in early JDK releases to replace the + * system wide implementation of {@code DatagramSocket}. It has been mostly + * obsolete since Java 1.4. If required, a {@code DatagramSocket} can be + * created to use a custom implementation by extending {@code DatagramSocket} + * and using the {@linkplain #DatagramSocket(DatagramSocketImpl) protected + * constructor} that takes an {@linkplain DatagramSocketImpl implementation} + * as a parameter. */ + @Deprecated(since = "17") public static synchronized void setDatagramSocketImplFactory(DatagramSocketImplFactory fac) throws IOException @@ -1038,6 +1235,106 @@ public Set> supportedOptions() { return delegate().supportedOptions(); } + /** + * Joins a multicast group. + * + *

    In order to join a multicast group, the caller should specify + * the IP address of the multicast group to join, and the local + * {@linkplain NetworkInterface network interface} to receive multicast + * packets from. + *

      + *
    • The {@code mcastaddr} argument indicates the IP address + * of the multicast group to join. For historical reasons this is + * specified as a {@code SocketAddress}. + * The default implementation only supports {@link InetSocketAddress} and + * the {@link InetSocketAddress#getPort() port} information is ignored. + *
    • + *
    • The {@code netIf} argument specifies the local interface to receive + * multicast datagram packets, or {@code null} to defer to the interface + * set for outgoing multicast datagrams. + * If {@code null}, and no interface has been set, the behaviour is + * unspecified: any interface may be selected or the operation may fail + * with a {@code SocketException}. + *
    • + *
    + * + *

    It is possible to call this method several times to join + * several different multicast groups, or join the same group + * in several different networks. However, if the socket is already a + * member of the group, an {@link IOException} will be thrown. + * + *

    If there is a security manager, this method first + * calls its {@code checkMulticast} method with the {@code mcastaddr} + * argument as its argument. + * + * @apiNote The default interface for sending outgoing multicast datagrams + * can be configured with {@link #setOption(SocketOption, Object)} + * with {@link StandardSocketOptions#IP_MULTICAST_IF}. + * + * @param mcastaddr indicates the multicast address to join. + * @param netIf specifies the local interface to receive multicast + * datagram packets, or {@code null}. + * @throws IOException if there is an error joining, or when the address + * is not a multicast address, or the platform does not support + * multicasting + * @throws SecurityException if a security manager exists and its + * {@code checkMulticast} method doesn't allow the join. + * @throws IllegalArgumentException if mcastaddr is {@code null} or is a + * SocketAddress subclass not supported by this socket + * @see SecurityManager#checkMulticast(InetAddress) + * @see DatagramChannel#join(InetAddress, NetworkInterface) + * @see StandardSocketOptions#IP_MULTICAST_IF + * @since 17 + */ + public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) + throws IOException { + delegate().joinGroup(mcastaddr, netIf); + } + + /** + * Leave a multicast group on a specified local interface. + * + *

    If there is a security manager, this method first + * calls its {@code checkMulticast} method with the + * {@code mcastaddr} argument as its argument. + * + * @apiNote + * The {@code mcastaddr} and {@code netIf} arguments should identify + * a multicast group that was previously {@linkplain + * #joinGroup(SocketAddress, NetworkInterface) joined} by + * this {@code DatagramSocket}. + *

    It is possible to call this method several times to leave + * multiple different multicast groups previously joined, or leave + * the same group previously joined in multiple different networks. + * However, if the socket is not a member of the specified group + * in the specified network, an {@link IOException} will be + * thrown. + * + * @param mcastaddr is the multicast address to leave. This should + * contain the same IP address than that used for {@linkplain + * #joinGroup(SocketAddress, NetworkInterface) joining} + * the group. + * @param netIf specifies the local interface or {@code null} to defer + * to the interface set for outgoing multicast datagrams. + * If {@code null}, and no interface has been set, the behaviour + * is unspecified: any interface may be selected or the operation + * may fail with a {@code SocketException}. + * @throws IOException if there is an error leaving or when the address + * is not a multicast address. + * @throws SecurityException if a security manager exists and its + * {@code checkMulticast} method doesn't allow the operation. + * @throws IllegalArgumentException if mcastaddr is {@code null} or is a + * SocketAddress subclass not supported by this socket. + * @see SecurityManager#checkMulticast(InetAddress) + * @see #joinGroup(SocketAddress, NetworkInterface) + * @see StandardSocketOptions#IP_MULTICAST_IF + * @since 17 + */ + public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) + throws IOException { + delegate().leaveGroup(mcastaddr, netIf); + } + // Temporary solution until JDK-8237352 is addressed private static final SocketAddress NO_DELEGATE = new SocketAddress() {}; private static final boolean USE_PLAINDATAGRAMSOCKET = usePlainDatagramSocketImpl(); diff --git a/src/java.base/share/classes/java/net/MulticastSocket.java b/src/java.base/share/classes/java/net/MulticastSocket.java index c1ebaa72ba2..23c534d0abe 100644 --- a/src/java.base/share/classes/java/net/MulticastSocket.java +++ b/src/java.base/share/classes/java/net/MulticastSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ * with the desired port, then invoking the * joinGroup(InetAddress groupAddr) * method: - *

    + * 
    {@code
      * // join a Multicast group and send the group salutations
      * ...
      * String msg = "Hello";
    @@ -65,7 +65,7 @@
      * ...
      * // OK, I'm done talking - leave the group...
      * s.leaveGroup(group, netIf);
    - * 
    + * }
    * * When one sends a message to a multicast group, all subscribing * recipients to that host and port receive the message (within the @@ -86,46 +86,19 @@ * supports the {@link #setOption(SocketOption, Object) setOption} * and {@link #getOption(SocketOption) getOption} methods to set * and query socket options. - * In addition to the socket options supported by - * {@code DatagramSocket}, a - * {@code MulticastSocket} supports the following socket options: - *
    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Socket options
    Option NameDescription
    {@link java.net.StandardSocketOptions#IP_MULTICAST_IF IP_MULTICAST_IF} The network interface for Internet Protocol (IP) multicast datagrams
    {@link java.net.StandardSocketOptions#IP_MULTICAST_TTL - * IP_MULTICAST_TTL} The time-to-live for Internet Protocol (IP) multicast - * datagrams
    {@link java.net.StandardSocketOptions#IP_MULTICAST_LOOP - * IP_MULTICAST_LOOP} Loopback for Internet Protocol (IP) multicast datagrams
    - *
    + * The set of supported socket options + * is defined in {@code DatagramSocket}. * Additional (implementation specific) options may also be supported. * - * @apiNote {@link DatagramChannel} implements the {@link MulticastChannel} interface + * @apiNote {@link DatagramSocket} may be used directly for + * sending and receiving multicast datagrams. + * {@link DatagramChannel} implements the {@link MulticastChannel} interface * and provides an alternative API for sending and receiving multicast datagrams. * The {@link MulticastChannel} API supports both {@linkplain * MulticastChannel#join(InetAddress, NetworkInterface) any-source} and * {@linkplain MulticastChannel#join(InetAddress, NetworkInterface, InetAddress) - * source-specific} multicast. + * source-specific} multicast. Consider using {@link DatagramChannel} for + * multicasting. * * @author Pavani Diwanji * @since 1.1 @@ -243,7 +216,7 @@ public MulticastSocket(SocketAddress bindaddr) throws IOException { * @param ttl the time-to-live * @throws IOException if an I/O exception occurs * while setting the default time-to-live value - * @deprecated use the setTimeToLive method instead, which uses + * @deprecated use the {@link #setTimeToLive(int)} method instead, which uses * int instead of byte as the type for ttl. * @see #getTTL() */ @@ -262,6 +235,10 @@ public void setTTL(byte ttl) throws IOException { * Multicast packets sent with a TTL of {@code 0} are not transmitted * on the network but may be delivered locally. * + * @apiNote + * This method is equivalent to calling {@link #setOption(SocketOption, Object) + * setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl)}. + * * @param ttl * the time-to-live * @@ -270,6 +247,7 @@ public void setTTL(byte ttl) throws IOException { * default time-to-live value * * @see #getTimeToLive() + * @see StandardSocketOptions#IP_MULTICAST_TTL * @since 1.2 */ public void setTimeToLive(int ttl) throws IOException { @@ -283,8 +261,8 @@ public void setTimeToLive(int ttl) throws IOException { * @throws IOException if an I/O exception occurs * while getting the default time-to-live value * @return the default time-to-live value - * @deprecated use the getTimeToLive method instead, which returns - * an int instead of a byte. + * @deprecated use the {@link #getTimeToLive()} method instead, + * which returns an int instead of a byte. * @see #setTTL(byte) */ @Deprecated @@ -295,10 +273,16 @@ public byte getTTL() throws IOException { /** * Get the default time-to-live for multicast packets sent out on * the socket. + * + * @apiNote + * This method is equivalent to calling {@link #getOption(SocketOption) + * getOption(StandardSocketOptions.IP_MULTICAST_TTL)}. + * * @throws IOException if an I/O exception occurs while * getting the default time-to-live value * @return the default time-to-live value * @see #setTimeToLive(int) + * @see StandardSocketOptions#IP_MULTICAST_TTL * @since 1.2 */ public int getTimeToLive() throws IOException { @@ -313,6 +297,11 @@ public int getTimeToLive() throws IOException { * calls its {@code checkMulticast} method with the * {@code mcastaddr} argument as its argument. * + * @apiNote + * Calling this method is equivalent to calling + * {@link #joinGroup(SocketAddress, NetworkInterface) + * joinGroup(new InetSocketAddress(mcastaddr, 0), null)}. + * * @param mcastaddr is the multicast address to join * @throws IOException if there is an error joining, * or when the address is not a multicast address, @@ -337,6 +326,11 @@ public void joinGroup(InetAddress mcastaddr) throws IOException { * calls its {@code checkMulticast} method with the * {@code mcastaddr} argument as its argument. * + * @apiNote + * Calling this method is equivalent to calling + * {@link #leaveGroup(SocketAddress, NetworkInterface) + * leaveGroup(new InetSocketAddress(mcastaddr, 0), null)}. + * * @param mcastaddr is the multicast address to leave * @throws IOException if there is an error leaving * or when the address is not a multicast address. @@ -353,65 +347,38 @@ public void leaveGroup(InetAddress mcastaddr) throws IOException { } /** - * Joins the specified multicast group at the specified interface. - * - *

    If there is a security manager, this method first - * calls its {@code checkMulticast} method - * with the {@code mcastaddr} argument - * as its argument. - * - * @param mcastaddr is the multicast address to join - * @param netIf specifies the local interface to receive multicast - * datagram packets, or {@code null} to defer to the interface set by - * {@link MulticastSocket#setInterface(InetAddress)} or - * {@link MulticastSocket#setNetworkInterface(NetworkInterface)}. - * If {@code null}, and no interface has been set, the behaviour is - * unspecified: any interface may be selected or the operation may fail - * with a {@code SocketException}. - * @throws IOException if there is an error joining, or when the address - * is not a multicast address, or the platform does not support - * multicasting - * @throws SecurityException if a security manager exists and its - * {@code checkMulticast} method doesn't allow the join. - * @throws IllegalArgumentException if mcastaddr is {@code null} or is a - * SocketAddress subclass not supported by this socket + * {@inheritDoc} + * @throws IOException {@inheritDoc} + * @throws SecurityException {@inheritDoc} + * @throws IllegalArgumentException {@inheritDoc} * @see SecurityManager#checkMulticast(InetAddress) * @see DatagramChannel#join(InetAddress, NetworkInterface) - * @since 1.4 + * @see StandardSocketOptions#IP_MULTICAST_IF + * @see #setNetworkInterface(NetworkInterface) + * @see #setInterface(InetAddress) + * @since 1.4 */ + @Override public void joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) - throws IOException { - delegate().joinGroup(mcastaddr, netIf); + throws IOException { + super.joinGroup(mcastaddr, netIf); } /** - * Leave a multicast group on a specified local interface. - * - *

    If there is a security manager, this method first - * calls its {@code checkMulticast} method with the - * {@code mcastaddr} argument as its argument. - * - * @param mcastaddr is the multicast address to leave - * @param netIf specifies the local interface or {@code null} to defer - * to the interface set by - * {@link MulticastSocket#setInterface(InetAddress)} or - * {@link MulticastSocket#setNetworkInterface(NetworkInterface)}. - * If {@code null}, and no interface has been set, the behaviour - * is unspecified: any interface may be selected or the operation - * may fail with a {@code SocketException}. - * @throws IOException if there is an error leaving or when the address - * is not a multicast address. - * @throws SecurityException if a security manager exists and its - * {@code checkMulticast} method doesn't allow the operation. - * @throws IllegalArgumentException if mcastaddr is {@code null} or is a - * SocketAddress subclass not supported by this socket. + * {@inheritDoc} + * @apiNote {@inheritDoc} + * @throws IOException {@inheritDoc} + * @throws SecurityException {@inheritDoc} + * @throws IllegalArgumentException {@inheritDoc} * @see SecurityManager#checkMulticast(InetAddress) - * @since 1.4 + * @see #joinGroup(SocketAddress, NetworkInterface) + * @since 1.4 */ + @Override public void leaveGroup(SocketAddress mcastaddr, NetworkInterface netIf) - throws IOException { - delegate().leaveGroup(mcastaddr, netIf); - } + throws IOException { + super.leaveGroup(mcastaddr, netIf); + } /** * Set the multicast network interface used by methods @@ -455,10 +422,15 @@ public InetAddress getInterface() throws SocketException { * Specify the network interface for outgoing multicast datagrams * sent on this socket. * + * @apiNote + * This method is equivalent to calling {@link #setOption(SocketOption, Object) + * setOption(StandardSocketOptions.IP_MULTICAST_IF, netIf)}. + * * @param netIf the interface * @throws SocketException if there is an error in * the underlying protocol, such as a TCP error. * @see #getNetworkInterface() + * @see StandardSocketOptions#IP_MULTICAST_IF * @since 1.4 */ public void setNetworkInterface(NetworkInterface netIf) @@ -467,7 +439,13 @@ public void setNetworkInterface(NetworkInterface netIf) } /** - * Get the multicast network interface set. + * Get the multicast network interface set for outgoing multicast + * datagrams sent from this socket. + * + * @apiNote + * When an interface is set, this method is equivalent + * to calling {@link #getOption(SocketOption) + * getOption(StandardSocketOptions.IP_MULTICAST_IF)}. * * @throws SocketException if there is an error in * the underlying protocol, such as a TCP error. @@ -475,6 +453,7 @@ public void setNetworkInterface(NetworkInterface netIf) * NetworkInterface is returned when there is no interface set; it has * a single InetAddress to represent any local address. * @see #setNetworkInterface(NetworkInterface) + * @see StandardSocketOptions#IP_MULTICAST_IF * @since 1.4 */ public NetworkInterface getNetworkInterface() throws SocketException { @@ -564,12 +543,12 @@ public boolean getLoopbackMode() throws SocketException { * * * @deprecated Use the following code or its equivalent instead: - * ...... - * int ttl = mcastSocket.getTimeToLive(); - * mcastSocket.setTimeToLive(newttl); + *

    {@code   ......
    +     *  int ttl = mcastSocket.getOption(StandardSocketOptions.IP_MULTICAST_TTL);
    +     *  mcastSocket.setOption(StandardSocketOptions.IP_MULTICAST_TTL, newttl);
          *  mcastSocket.send(p);
    -     *  mcastSocket.setTimeToLive(ttl);
    -     *  ......
    +     *  mcastSocket.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl);
    +     *  ......}
    * * @see DatagramSocket#send * @see DatagramSocket#receive diff --git a/src/java.base/share/classes/java/net/ServerSocket.java b/src/java.base/share/classes/java/net/ServerSocket.java index 249c09b9674..30574780f14 100644 --- a/src/java.base/share/classes/java/net/ServerSocket.java +++ b/src/java.base/share/classes/java/net/ServerSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,10 +41,7 @@ * based on that request, and then possibly returns a result to the requester. *

    * The actual work of the server socket is performed by an instance - * of the {@code SocketImpl} class. An application can - * change the socket factory that creates the socket - * implementation to configure itself to create sockets - * appropriate to the local firewall. + * of the {@code SocketImpl} class. * *

    The {@code ServerSocket} class defines convenience * methods to set and get several socket options. This class also @@ -76,7 +73,6 @@ * Additional (implementation specific) options may also be supported. * * @see java.net.SocketImpl - * @see java.net.ServerSocket#setSocketFactory(java.net.SocketImplFactory) * @see java.nio.channels.ServerSocketChannel * @since 1.0 */ @@ -164,8 +160,6 @@ public ServerSocket() throws IOException { * 0 and 65535, inclusive. * * @see java.net.SocketImpl - * @see java.net.SocketImplFactory#createSocketImpl() - * @see java.net.ServerSocket#setSocketFactory(java.net.SocketImplFactory) * @see SecurityManager#checkListen */ public ServerSocket(int port) throws IOException { @@ -217,8 +211,6 @@ public ServerSocket(int port) throws IOException { * 0 and 65535, inclusive. * * @see java.net.SocketImpl - * @see java.net.SocketImplFactory#createSocketImpl() - * @see java.net.ServerSocket#setSocketFactory(java.net.SocketImplFactory) * @see SecurityManager#checkListen */ public ServerSocket(int port, int backlog) throws IOException { @@ -929,7 +921,17 @@ public String toString() { * {@code checkSetFactory} method doesn't allow the operation. * @see java.net.SocketImplFactory#createSocketImpl() * @see SecurityManager#checkSetFactory + * @deprecated Use a {@link javax.net.ServerSocketFactory} and subclass {@code ServerSocket} + * directly. + *
    This method provided a way in early JDK releases to replace the + * system wide implementation of {@code ServerSocket}. It has been mostly + * obsolete since Java 1.4. If required, a {@code ServerSocket} can be + * created to use a custom implementation by extending {@code ServerSocket} + * and using the {@linkplain #ServerSocket(SocketImpl) protected + * constructor} that takes an {@linkplain SocketImpl implementation} + * as a parameter. */ + @Deprecated(since = "17") public static synchronized void setSocketFactory(SocketImplFactory fac) throws IOException { if (factory != null) { throw new SocketException("factory already defined"); diff --git a/src/java.base/share/classes/java/net/Socket.java b/src/java.base/share/classes/java/net/Socket.java index 3357dbfe777..82509978947 100644 --- a/src/java.base/share/classes/java/net/Socket.java +++ b/src/java.base/share/classes/java/net/Socket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,8 +33,6 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.nio.channels.SocketChannel; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Objects; import java.util.Set; import java.util.Collections; @@ -45,10 +43,7 @@ * between two machines. *

    * The actual work of the socket is performed by an instance of the - * {@code SocketImpl} class. An application, by changing - * the socket factory that creates the socket implementation, - * can configure itself to create sockets appropriate to the local - * firewall. + * {@code SocketImpl} class. * *

    The {@code Socket} class defines convenience * methods to set and get several socket options. This class also @@ -96,7 +91,6 @@ * * Additional (implementation specific) options may also be supported. * - * @see java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory) * @see java.net.SocketImpl * @see java.nio.channels.SocketChannel * @since 1.0 @@ -282,9 +276,7 @@ private static Void checkPermission(SocketImpl impl) { * @throws IllegalArgumentException if the port parameter is outside * the specified range of valid port values, which is between * 0 and 65535, inclusive. - * @see java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory) * @see java.net.SocketImpl - * @see java.net.SocketImplFactory#createSocketImpl() * @see SecurityManager#checkConnect */ public Socket(String host, int port) @@ -318,9 +310,7 @@ public Socket(String host, int port) * the specified range of valid port values, which is between * 0 and 65535, inclusive. * @throws NullPointerException if {@code address} is null. - * @see java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory) * @see java.net.SocketImpl - * @see java.net.SocketImplFactory#createSocketImpl() * @see SecurityManager#checkConnect */ public Socket(InetAddress address, int port) throws IOException { @@ -448,9 +438,7 @@ public Socket(InetAddress address, int port, InetAddress localAddr, * @throws IllegalArgumentException if the port parameter is outside * the specified range of valid port values, which is between * 0 and 65535, inclusive. - * @see java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory) * @see java.net.SocketImpl - * @see java.net.SocketImplFactory#createSocketImpl() * @see SecurityManager#checkConnect * @deprecated Use DatagramSocket instead for UDP transport. */ @@ -492,9 +480,7 @@ public Socket(String host, int port, boolean stream) throws IOException { * the specified range of valid port values, which is between * 0 and 65535, inclusive. * @throws NullPointerException if {@code host} is null. - * @see java.net.Socket#setSocketImplFactory(java.net.SocketImplFactory) * @see java.net.SocketImpl - * @see java.net.SocketImplFactory#createSocketImpl() * @see SecurityManager#checkConnect * @deprecated Use DatagramSocket instead for UDP transport. */ @@ -1761,7 +1747,17 @@ static SocketImplFactory socketImplFactory() { * {@code checkSetFactory} method doesn't allow the operation. * @see java.net.SocketImplFactory#createSocketImpl() * @see SecurityManager#checkSetFactory - */ + * @deprecated Use a {@link javax.net.SocketFactory} and subclass {@code Socket} + * directly. + *
    This method provided a way in early JDK releases to replace the + * system wide implementation of {@code Socket}. It has been mostly + * obsolete since Java 1.4. If required, a {@code Socket} can be + * created to use a custom implementation by extending {@code Socket} + * and using the {@linkplain #Socket(SocketImpl) protected + * constructor} that takes an {@linkplain SocketImpl implementation} + * as a parameter. + */ + @Deprecated(since = "17") public static synchronized void setSocketImplFactory(SocketImplFactory fac) throws IOException { diff --git a/src/java.base/share/classes/java/nio/MappedByteBuffer.java b/src/java.base/share/classes/java/nio/MappedByteBuffer.java index c8a0509218a..bc2abfd25be 100644 --- a/src/java.base/share/classes/java/nio/MappedByteBuffer.java +++ b/src/java.base/share/classes/java/nio/MappedByteBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ import jdk.internal.access.foreign.MemorySegmentProxy; import jdk.internal.access.foreign.UnmapperProxy; import jdk.internal.misc.ScopedMemoryAccess; +import jdk.internal.misc.Unsafe; /** @@ -132,7 +133,7 @@ public boolean isSync() { @Override public void unmap() { - throw new UnsupportedOperationException(); + Unsafe.getUnsafe().invokeCleaner(MappedByteBuffer.this); } } : null; } diff --git a/src/java.base/share/classes/java/nio/file/FileChannelLinesSpliterator.java b/src/java.base/share/classes/java/nio/file/FileChannelLinesSpliterator.java index 7ec7220d8f9..44419ae26dd 100644 --- a/src/java.base/share/classes/java/nio/file/FileChannelLinesSpliterator.java +++ b/src/java.base/share/classes/java/nio/file/FileChannelLinesSpliterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,8 +39,12 @@ import java.util.HashSet; import java.util.Set; import java.util.Spliterator; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; +import jdk.internal.access.SharedSecrets; +import jdk.internal.access.JavaNioAccess; + /** * A file-based lines spliterator, leveraging a shared mapped byte buffer and * associated file channel, covering lines of a file for character encodings @@ -84,19 +88,31 @@ final class FileChannelLinesSpliterator implements Spliterator { // Non-null when traversing private BufferedReader reader; + // Number of references to the shared mapped buffer. Initialized to unity + // when the buffer is created by the root spliterator. Incremented in the + // sub-spliterator constructor. Decremented when 'buffer' transitions from + // non-null to null, either when traversing begins or if the spliterator is + // closed before traversal. If the count is zero after decrementing, then + // the buffer is unmapped. + private final AtomicInteger bufRefCount; + FileChannelLinesSpliterator(FileChannel fc, Charset cs, int index, int fence) { this.fc = fc; this.cs = cs; this.index = index; this.fence = fence; + this.bufRefCount = new AtomicInteger(); } - private FileChannelLinesSpliterator(FileChannel fc, Charset cs, int index, int fence, ByteBuffer buffer) { + private FileChannelLinesSpliterator(FileChannel fc, Charset cs, int index, + int fence, ByteBuffer buffer, AtomicInteger bufRefCount) { this.fc = fc; - this.buffer = buffer; this.cs = cs; this.index = index; this.fence = fence; + this.buffer = buffer; + this.bufRefCount = bufRefCount; + this.bufRefCount.incrementAndGet(); } @Override @@ -167,7 +183,7 @@ public void close() throws IOException { private String readLine() { if (reader == null) { reader = getBufferedReader(); - buffer = null; + unmap(); } try { @@ -178,13 +194,6 @@ private String readLine() { } private ByteBuffer getMappedByteBuffer() { - // TODO can the mapped byte buffer be explicitly unmapped? - // It's possible, via a shared-secret mechanism, when either - // 1) the spliterator starts traversing, although traversal can - // happen concurrently for mulitple spliterators, so care is - // needed in this case; or - // 2) when the stream is closed using some shared holder to pass - // the mapped byte buffer when it is created. try { return fc.map(FileChannel.MapMode.READ_ONLY, 0, fence); } catch (IOException e) { @@ -201,6 +210,7 @@ public Spliterator trySplit() { ByteBuffer b; if ((b = buffer) == null) { b = buffer = getMappedByteBuffer(); + bufRefCount.set(1); } final int hi = fence, lo = index; @@ -246,7 +256,8 @@ public Spliterator trySplit() { // The left spliterator will have the line-separator at the end return (mid > lo && mid < hi) - ? new FileChannelLinesSpliterator(fc, cs, lo, index = mid, b) + ? new FileChannelLinesSpliterator(fc, cs, lo, index = mid, + b, bufRefCount) : null; } @@ -267,4 +278,22 @@ public long getExactSizeIfKnown() { public int characteristics() { return Spliterator.ORDERED | Spliterator.NONNULL; } + + private void unmap() { + if (buffer != null) { + ByteBuffer b = buffer; + buffer = null; + if (bufRefCount.decrementAndGet() == 0) { + JavaNioAccess nioAccess = SharedSecrets.getJavaNioAccess(); + try { + nioAccess.unmapper(b).unmap(); + } catch (UnsupportedOperationException ignored) { + } + } + } + } + + void close() { + unmap(); + } } diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index d3bdc3fd0e7..db61e6d19f7 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -4121,9 +4121,11 @@ private static Stream createFileChannelLinesStream(FileChannel fc, Chars // FileChannel.size() may in certain circumstances return zero // for a non-zero length file so disallow this case. if (length > 0 && length <= Integer.MAX_VALUE) { - Spliterator s = new FileChannelLinesSpliterator(fc, cs, 0, (int) length); - return StreamSupport.stream(s, false) - .onClose(Files.asUncheckedRunnable(fc)); + FileChannelLinesSpliterator fcls = + new FileChannelLinesSpliterator(fc, cs, 0, (int) length); + return StreamSupport.stream(fcls, false) + .onClose(Files.asUncheckedRunnable(fc)) + .onClose(() -> fcls.close()); } } catch (Error|RuntimeException|IOException e) { try { diff --git a/src/java.base/share/classes/java/util/Formatter.java b/src/java.base/share/classes/java/util/Formatter.java index e5934b28e78..c4dc4c0b85d 100644 --- a/src/java.base/share/classes/java/util/Formatter.java +++ b/src/java.base/share/classes/java/util/Formatter.java @@ -1832,7 +1832,7 @@ * *

    The {@code '-'} flag defined for General * conversions applies. If any other flags are provided, then a - * {@link FormatFlagsConversionMismatchException} will be thrown. + * {@link IllegalFormatFlagsException } will be thrown. * *

    The precision is not applicable. If the precision is specified an * {@link IllegalFormatPrecisionException} will be thrown. diff --git a/src/java.base/share/classes/java/util/ResourceBundle.java b/src/java.base/share/classes/java/util/ResourceBundle.java index 1bf84f683a5..d40dad3990e 100644 --- a/src/java.base/share/classes/java/util/ResourceBundle.java +++ b/src/java.base/share/classes/java/util/ResourceBundle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2890,15 +2890,17 @@ protected List createObject(BaseLocale base) { } if (language.equals("nb") || isNorwegianBokmal) { List tmpList = getDefaultList("nb", script, region, variant); - // Insert a locale replacing "nb" with "no" for every list entry + // Insert a locale replacing "nb" with "no" for every list entry with precedence List bokmalList = new LinkedList<>(); - for (Locale l : tmpList) { - bokmalList.add(l); - if (l.getLanguage().isEmpty()) { + for (Locale l_nb : tmpList) { + var isRoot = l_nb.getLanguage().isEmpty(); + var l_no = Locale.getInstance(isRoot ? "" : "no", + l_nb.getScript(), l_nb.getCountry(), l_nb.getVariant(), null); + bokmalList.add(isNorwegianBokmal ? l_no : l_nb); + if (isRoot) { break; } - bokmalList.add(Locale.getInstance("no", l.getScript(), l.getCountry(), - l.getVariant(), null)); + bokmalList.add(isNorwegianBokmal ? l_nb : l_no); } return bokmalList; } else if (language.equals("nn") || isNorwegianNynorsk) { diff --git a/src/java.base/share/classes/java/util/ServiceLoader.java b/src/java.base/share/classes/java/util/ServiceLoader.java index 35f38934368..559b441006c 100644 --- a/src/java.base/share/classes/java/util/ServiceLoader.java +++ b/src/java.base/share/classes/java/util/ServiceLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -280,7 +280,7 @@ *

    The provider-configuration file must be encoded in UTF-8. * Space and tab characters surrounding each service provider's name, as well as * blank lines, are ignored. The comment character is {@code '#'} - * ({@code '\u0023'} NUMBER SIGN); + * ({@code U+0023} NUMBER SIGN); * on each line all characters following the first comment character are ignored. * If a service provider class name is listed more than once in a * provider-configuration file then the duplicate is ignored. If a service diff --git a/src/java.base/share/classes/javax/crypto/KeyAgreement.java b/src/java.base/share/classes/javax/crypto/KeyAgreement.java index 6435f66c29b..194be62c426 100644 --- a/src/java.base/share/classes/javax/crypto/KeyAgreement.java +++ b/src/java.base/share/classes/javax/crypto/KeyAgreement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,9 @@ * with two other parties, {@code doPhase} needs to be called twice, * the first time setting the {@code lastPhase} flag to * {@code false}, and the second time setting it to {@code true}. - * There may be any number of parties involved in a key exchange. + * There may be any number of parties involved in a key exchange. However, + * support for key exchanges with more than two parties is implementation + * specific or as specified by the standard key agreement algorithm. * *

    Every implementation of the Java platform is required to support the * following standard {@code KeyAgreement} algorithm: diff --git a/src/java.base/share/classes/jdk/internal/event/DeserializationEvent.java b/src/java.base/share/classes/jdk/internal/event/DeserializationEvent.java new file mode 100644 index 00000000000..0caf61318fd --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/event/DeserializationEvent.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.event; + +/** + * Event details relating to deserialization. + */ + +public final class DeserializationEvent extends Event { + public boolean filterConfigured; + public String filterStatus; + public Class type; + public int arrayLength; + public long objectReferences; + public long depth; + public long bytesRead; + public Class exceptionType; + public String exceptionMessage; +} diff --git a/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java b/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java index ee77794aa1c..4f3da93df48 100644 --- a/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java +++ b/src/java.base/share/classes/jdk/internal/jimage/BasicImageReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -249,57 +249,69 @@ public ImageStringsReader getStrings() { return stringsReader; } - public synchronized ImageLocation findLocation(String module, String name) { - Objects.requireNonNull(module); - Objects.requireNonNull(name); - // Details of the algorithm used here can be found in - // jdk.tools.jlink.internal.PerfectHashBuilder. - int count = header.getTableLength(); - int index = redirect.get(ImageStringsReader.hashCode(module, name) % count); - + public ImageLocation findLocation(String module, String name) { + int index = getLocationIndex(module, name); if (index < 0) { - // index is twos complement of location attributes index. - index = -index - 1; - } else if (index > 0) { - // index is hash seed needed to compute location attributes index. - index = ImageStringsReader.hashCode(module, name, index) % count; - } else { - // No entry. return null; } - long[] attributes = getAttributes(offsets.get(index)); - if (!ImageLocation.verify(module, name, attributes, stringsReader)) { return null; } return new ImageLocation(attributes, stringsReader); } - public synchronized ImageLocation findLocation(String name) { - Objects.requireNonNull(name); - // Details of the algorithm used here can be found in - // jdk.tools.jlink.internal.PerfectHashBuilder. + public ImageLocation findLocation(String name) { + int index = getLocationIndex(name); + if (index < 0) { + return null; + } + long[] attributes = getAttributes(offsets.get(index)); + if (!ImageLocation.verify(name, attributes, stringsReader)) { + return null; + } + return new ImageLocation(attributes, stringsReader); + } + + public boolean verifyLocation(String module, String name) { + int index = getLocationIndex(module, name); + if (index < 0) { + return false; + } + int locationOffset = offsets.get(index); + return ImageLocation.verify(module, name, locations, locationOffset, stringsReader); + } + + // Details of the algorithm used here can be found in + // jdk.tools.jlink.internal.PerfectHashBuilder. + public int getLocationIndex(String name) { int count = header.getTableLength(); int index = redirect.get(ImageStringsReader.hashCode(name) % count); - if (index < 0) { // index is twos complement of location attributes index. - index = -index - 1; + return -index - 1; } else if (index > 0) { // index is hash seed needed to compute location attributes index. - index = ImageStringsReader.hashCode(name, index) % count; + return ImageStringsReader.hashCode(name, index) % count; } else { // No entry. - return null; + return -1; } + } - long[] attributes = getAttributes(offsets.get(index)); - - if (!ImageLocation.verify(name, attributes, stringsReader)) { - return null; + private int getLocationIndex(String module, String name) { + int count = header.getTableLength(); + int index = redirect.get(ImageStringsReader.hashCode(module, name) % count); + if (index < 0) { + // index is twos complement of location attributes index. + return -index - 1; + } else if (index > 0) { + // index is hash seed needed to compute location attributes index. + return ImageStringsReader.hashCode(module, name, index) % count; + } else { + // No entry. + return -1; } - return new ImageLocation(attributes, stringsReader); } public String[] getEntryNames() { @@ -320,18 +332,21 @@ public long[] getAttributes(int offset) { if (offset < 0 || offset >= locations.limit()) { throw new IndexOutOfBoundsException("offset"); } - - ByteBuffer buffer = slice(locations, offset, locations.limit() - offset); - return ImageLocation.decompress(buffer); + return ImageLocation.decompress(locations, offset); } public String getString(int offset) { if (offset < 0 || offset >= strings.limit()) { throw new IndexOutOfBoundsException("offset"); } + return ImageStringsReader.stringFromByteBuffer(strings, offset); + } - ByteBuffer buffer = slice(strings, offset, strings.limit() - offset); - return ImageStringsReader.stringFromByteBuffer(buffer); + public int match(int offset, String string, int stringOffset) { + if (offset < 0 || offset >= strings.limit()) { + throw new IndexOutOfBoundsException("offset"); + } + return ImageStringsReader.stringFromByteBufferMatches(strings, offset, string, stringOffset); } private byte[] getBufferBytes(ByteBuffer buffer) { diff --git a/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java b/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java index f1b8f5594c3..f31c7291927 100644 --- a/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java +++ b/src/java.base/share/classes/jdk/internal/jimage/ImageLocation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,41 +59,26 @@ ImageStrings getStrings() { return strings; } - static long[] decompress(ByteBuffer bytes) { + static long[] decompress(ByteBuffer bytes, int offset) { Objects.requireNonNull(bytes); long[] attributes = new long[ATTRIBUTE_COUNT]; - if (bytes != null) { - while (bytes.hasRemaining()) { - int data = bytes.get() & 0xFF; - int kind = data >>> 3; - - if (kind == ATTRIBUTE_END) { - break; - } - - if (kind < ATTRIBUTE_END || ATTRIBUTE_COUNT <= kind) { - throw new InternalError( - "Invalid jimage attribute kind: " + kind); - } - - int length = (data & 0x7) + 1; - long value = 0; - - for (int j = 0; j < length; j++) { - value <<= 8; - - if (!bytes.hasRemaining()) { - throw new InternalError("Missing jimage attribute data"); - } - - value |= bytes.get() & 0xFF; - } - - attributes[kind] = value; + int limit = bytes.limit(); + while (offset < limit) { + int data = bytes.get(offset++) & 0xFF; + if (data <= 0x7) { // ATTRIBUTE_END + break; + } + int kind = data >>> 3; + if (ATTRIBUTE_COUNT <= kind) { + throw new InternalError( + "Invalid jimage attribute kind: " + kind); } - } + int length = (data & 0x7) + 1; + attributes[kind] = readValue(length, bytes, offset, limit); + offset += length; + } return attributes; } @@ -126,51 +111,105 @@ public boolean verify(String name) { /** * A simpler verification would be {@code name.equals(getFullName())}, but * by not creating the full name and enabling early returns we allocate - * fewer objects. Could possibly be made allocation free by extending - * ImageStrings to test if strings at an offset match the name region. + * fewer objects. */ static boolean verify(String name, long[] attributes, ImageStrings strings) { Objects.requireNonNull(name); final int length = name.length(); int index = 0; int moduleOffset = (int)attributes[ATTRIBUTE_MODULE]; - if (moduleOffset != 0) { - String module = strings.get(moduleOffset); - final int moduleLen = module.length(); + if (moduleOffset != 0 && length >= 1) { + int moduleLen = strings.match(moduleOffset, name, 1); index = moduleLen + 1; - if (length <= index + if (moduleLen < 0 + || length <= index || name.charAt(0) != '/' - || !name.regionMatches(1, module, 0, moduleLen) || name.charAt(index++) != '/') { return false; } } + return verifyName(null, name, index, length, 0, + (int) attributes[ATTRIBUTE_PARENT], + (int) attributes[ATTRIBUTE_BASE], + (int) attributes[ATTRIBUTE_EXTENSION], + strings); + } - return verifyName(name, index, length, attributes, strings); + static boolean verify(String module, String name, ByteBuffer locations, + int locationOffset, ImageStrings strings) { + int moduleOffset = 0; + int parentOffset = 0; + int baseOffset = 0; + int extOffset = 0; + + int limit = locations.limit(); + while (locationOffset < limit) { + int data = locations.get(locationOffset++) & 0xFF; + if (data <= 0x7) { // ATTRIBUTE_END + break; + } + int kind = data >>> 3; + if (ATTRIBUTE_COUNT <= kind) { + throw new InternalError( + "Invalid jimage attribute kind: " + kind); + } + + int length = (data & 0x7) + 1; + switch (kind) { + case ATTRIBUTE_MODULE: + moduleOffset = (int) readValue(length, locations, locationOffset, limit); + break; + case ATTRIBUTE_BASE: + baseOffset = (int) readValue(length, locations, locationOffset, limit); + break; + case ATTRIBUTE_PARENT: + parentOffset = (int) readValue(length, locations, locationOffset, limit); + break; + case ATTRIBUTE_EXTENSION: + extOffset = (int) readValue(length, locations, locationOffset, limit); + break; + } + locationOffset += length; + } + return verifyName(module, name, 0, name.length(), + moduleOffset, parentOffset, baseOffset, extOffset, strings); + } + + private static long readValue(int length, ByteBuffer buffer, int offset, int limit) { + long value = 0; + for (int j = 0; j < length; j++) { + value <<= 8; + if (offset >= limit) { + throw new InternalError("Missing jimage attribute data"); + } + value |= buffer.get(offset++) & 0xFF; + } + return value; } static boolean verify(String module, String name, long[] attributes, ImageStrings strings) { Objects.requireNonNull(module); Objects.requireNonNull(name); - int moduleOffset = (int)attributes[ATTRIBUTE_MODULE]; + return verifyName(module, name, 0, name.length(), + (int) attributes[ATTRIBUTE_MODULE], + (int) attributes[ATTRIBUTE_PARENT], + (int) attributes[ATTRIBUTE_BASE], + (int) attributes[ATTRIBUTE_EXTENSION], + strings); + } + + private static boolean verifyName(String module, String name, int index, int length, + int moduleOffset, int parentOffset, int baseOffset, int extOffset, ImageStrings strings) { + if (moduleOffset != 0) { - if (!module.equals(strings.get(moduleOffset))) { + if (strings.match(moduleOffset, module, 0) != module.length()) { return false; } } - - return verifyName(name, 0, name.length(), attributes, strings); - } - - private static boolean verifyName(String name, int index, int length, - long[] attributes, ImageStrings strings) { - - int parentOffset = (int) attributes[ATTRIBUTE_PARENT]; if (parentOffset != 0) { - String parent = strings.get(parentOffset); - final int parentLen = parent.length(); - if (!name.regionMatches(index, parent, 0, parentLen)) { + int parentLen = strings.match(parentOffset, name, index); + if (parentLen < 0) { return false; } index += parentLen; @@ -178,19 +217,19 @@ private static boolean verifyName(String name, int index, int length, return false; } } - String base = strings.get((int) attributes[ATTRIBUTE_BASE]); - final int baseLen = base.length(); - if (!name.regionMatches(index, base, 0, baseLen)) { + int baseLen = strings.match(baseOffset, name, index); + if (baseLen < 0) { return false; } index += baseLen; - int extOffset = (int) attributes[ATTRIBUTE_EXTENSION]; if (extOffset != 0) { - String extension = strings.get(extOffset); - int extLen = extension.length(); if (length <= index - || name.charAt(index++) != '.' - || !name.regionMatches(index, extension, 0, extLen)) { + || name.charAt(index++) != '.') { + return false; + } + + int extLen = strings.match(extOffset, name, index); + if (extLen < 0) { return false; } index += extLen; @@ -203,7 +242,6 @@ long getAttribute(int kind) { throw new InternalError( "Invalid jimage attribute kind: " + kind); } - return attributes[kind]; } @@ -212,7 +250,6 @@ String getAttributeString(int kind) { throw new InternalError( "Invalid jimage attribute kind: " + kind); } - return getStrings().get((int)attributes[kind]); } diff --git a/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java b/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java index d1f19a66c89..416188c9b22 100644 --- a/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java +++ b/src/java.base/share/classes/jdk/internal/jimage/ImageReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -148,6 +148,11 @@ public ImageLocation findLocation(String mn, String rn) { return reader.findLocation(mn, rn); } + public boolean verifyLocation(String mn, String rn) { + requireOpen(); + return reader.verifyLocation(mn, rn); + } + public ImageLocation findLocation(String name) { requireOpen(); return reader.findLocation(name); @@ -740,7 +745,7 @@ void addChild(Node node) { public void walk(Consumer consumer) { consumer.accept(this); - for ( Node child : children ) { + for (Node child : children) { if (child.isDirectory()) { ((Directory)child).walk(consumer); } else { diff --git a/src/java.base/share/classes/jdk/internal/jimage/ImageStrings.java b/src/java.base/share/classes/jdk/internal/jimage/ImageStrings.java index 6e7d76a8ff9..eea62e444de 100644 --- a/src/java.base/share/classes/jdk/internal/jimage/ImageStrings.java +++ b/src/java.base/share/classes/jdk/internal/jimage/ImageStrings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,17 @@ * to the jimage file provided by the shipped JDK by tools running on JDK 8. */ public interface ImageStrings { - public String get(int offset); + String get(int offset); + + int add(final String string); + + /** + * If there's a string at {@code offset} matching in full a substring of + * {@code string} starting at {@code stringOffset}, return the length + * of that string. Otherwise returns -1. Optional operation. + */ + default int match(int offset, String string, int stringOffset) { + throw new UnsupportedOperationException(); + } - public int add(final String string); } diff --git a/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java b/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java index d9900aa231e..f5773302004 100644 --- a/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java +++ b/src/java.base/share/classes/jdk/internal/jimage/ImageStringsReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import java.io.UTFDataFormatException; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.Objects; /** @@ -51,6 +52,11 @@ public String get(int offset) { return reader.getString(offset); } + @Override + public int match(int offset, String string, int stringOffset) { + return reader.match(offset, string, stringOffset); + } + @Override public int add(final String string) { throw new InternalError("Can not add strings at runtime"); @@ -69,9 +75,9 @@ public static int hashCode(String module, String name) { } public static int hashCode(String module, String name, int seed) { - seed = unmaskedHashCode("/", seed); + seed = (seed * HASH_MULTIPLIER) ^ ('/'); seed = unmaskedHashCode(module, seed); - seed = unmaskedHashCode("/", seed); + seed = (seed * HASH_MULTIPLIER) ^ ('/'); seed = unmaskedHashCode(name, seed); return seed & POSITIVE_MASK; } @@ -81,8 +87,7 @@ public static int unmaskedHashCode(String s, int seed) { byte[] buffer = null; for (int i = 0; i < slen; i++) { - char ch = s.charAt(i); - int uch = ch & 0xFFFF; + int uch = s.charAt(i); if ((uch & ~0x7F) != 0) { if (buffer == null) { @@ -183,29 +188,38 @@ public static String stringFromMUTF8(byte[] bytes) { return stringFromMUTF8(bytes, 0, bytes.length); } - static int charsFromByteBufferLength(ByteBuffer buffer) { + /** + * Calculates the number of characters in the String present at the + * specified offset. As an optimization, the length returned will + * be positive if the characters are all ASCII, and negative otherwise. + */ + private static int charsFromByteBufferLength(ByteBuffer buffer, int offset) { int length = 0; - while(buffer.hasRemaining()) { - byte ch = buffer.get(); + int limit = buffer.limit(); + boolean asciiOnly = true; + while (offset < limit) { + byte ch = buffer.get(offset++); - if (ch == 0) { - return length; + if (ch < 0) { + asciiOnly = false; + } else if (ch == 0) { + return asciiOnly ? length : -length; } if ((ch & 0xC0) != 0x80) { length++; } } - throw new InternalError("No terminating zero byte for modified UTF-8 byte sequence"); } - static void charsFromByteBuffer(char[] chars, ByteBuffer buffer) { + private static void charsFromByteBuffer(char[] chars, ByteBuffer buffer, int offset) { int j = 0; - while(buffer.hasRemaining()) { - byte ch = buffer.get(); + int limit = buffer.limit(); + while (offset < limit) { + byte ch = buffer.get(offset++); if (ch == 0) { return; @@ -218,7 +232,7 @@ static void charsFromByteBuffer(char[] chars, ByteBuffer buffer) { int mask = 0x40; while ((uch & mask) != 0) { - ch = buffer.get(); + ch = buffer.get(offset++); if ((ch & 0xC0) != 0x80) { throw new InternalError("Bad continuation in " + @@ -242,14 +256,62 @@ static void charsFromByteBuffer(char[] chars, ByteBuffer buffer) { } public static String stringFromByteBuffer(ByteBuffer buffer) { - int length = charsFromByteBufferLength(buffer); - buffer.rewind(); - char[] chars = new char[length]; - charsFromByteBuffer(chars, buffer); + return stringFromByteBuffer(buffer, 0); + } + /* package-private */ + static String stringFromByteBuffer(ByteBuffer buffer, int offset) { + int length = charsFromByteBufferLength(buffer, offset); + if (length > 0) { + byte[] asciiBytes = new byte[length]; + // Ideally we could use buffer.get(offset, asciiBytes, 0, length) + // here, but that was introduced in JDK 13 + for (int i = 0; i < length; i++) { + asciiBytes[i] = buffer.get(offset++); + } + return new String(asciiBytes, StandardCharsets.US_ASCII); + } + char[] chars = new char[-length]; + charsFromByteBuffer(chars, buffer, offset); return new String(chars); } + /* package-private */ + static int stringFromByteBufferMatches(ByteBuffer buffer, int offset, String string, int stringOffset) { + // ASCII fast-path + int limit = buffer.limit(); + int current = offset; + int slen = string.length(); + while (current < limit) { + byte ch = buffer.get(current); + if (ch <= 0) { + if (ch == 0) { + // Match + return current - offset; + } + // non-ASCII byte, run slow-path from current offset + break; + } + if (slen <= stringOffset || string.charAt(stringOffset) != (char)ch) { + // No match + return -1; + } + stringOffset++; + current++; + } + // invariant: remainder of the string starting at current is non-ASCII, + // so return value from charsFromByteBufferLength will be negative + int length = -charsFromByteBufferLength(buffer, current); + char[] chars = new char[length]; + charsFromByteBuffer(chars, buffer, current); + for (int i = 0; i < length; i++) { + if (string.charAt(stringOffset++) != chars[i]) { + return -1; + } + } + return length; + } + static int mutf8FromStringLength(String s) { int length = 0; int slen = s.length(); diff --git a/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java b/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java index 4c50d6f1746..dae3b8f3c20 100644 --- a/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java +++ b/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ private static String newName() { } /** - * Returns a new InnocuousThread with an auto-generated thread name + * Returns a new InnocuousThread with an auto-generated thread name, * and its context class loader is set to the system class loader. */ public static Thread newThread(Runnable target) { @@ -62,14 +62,22 @@ public static Thread newThread(Runnable target) { * set to the system class loader. */ public static Thread newThread(String name, Runnable target) { + return newThread(name, target, -1); + } + /** + * Returns a new InnocuousThread with its context class loader + * set to the system class loader. The thread priority will be + * set to the given priority. + */ + public static Thread newThread(String name, Runnable target, int priority) { + if (System.getSecurityManager() == null) { + return createThread(name, target, ClassLoader.getSystemClassLoader(), priority); + } return AccessController.doPrivileged( new PrivilegedAction() { @Override public Thread run() { - return new InnocuousThread(INNOCUOUSTHREADGROUP, - target, - name, - ClassLoader.getSystemClassLoader()); + return createThread(name, target, ClassLoader.getSystemClassLoader(), priority); } }); } @@ -86,16 +94,35 @@ public static Thread newSystemThread(Runnable target) { * Returns a new InnocuousThread with null context class loader. */ public static Thread newSystemThread(String name, Runnable target) { + return newSystemThread(name, target, -1); + } + + /** + * Returns a new InnocuousThread with null context class loader. + * Thread priority is set to the given priority. + */ + public static Thread newSystemThread(String name, Runnable target, int priority) { + if (System.getSecurityManager() == null) { + return createThread(name, target, null, priority); + } return AccessController.doPrivileged( new PrivilegedAction() { @Override public Thread run() { - return new InnocuousThread(INNOCUOUSTHREADGROUP, - target, name, null); + return createThread(name, target, null, priority); } }); } + private static Thread createThread(String name, Runnable target, ClassLoader loader, int priority) { + Thread t = new InnocuousThread(INNOCUOUSTHREADGROUP, + target, name, loader); + if (priority >= 0) { + t.setPriority(priority); + } + return t; + } + private InnocuousThread(ThreadGroup group, Runnable target, String name, ClassLoader tccl) { super(group, target, name, 0L, false); UNSAFE.putReferenceRelease(this, INHERITEDACCESSCONTROLCONTEXT, ACC); @@ -167,13 +194,17 @@ public void run() { group = parent; } final ThreadGroup root = group; - INNOCUOUSTHREADGROUP = AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public ThreadGroup run() { - return new ThreadGroup(root, "InnocuousThreadGroup"); - } - }); + if (System.getSecurityManager() == null) { + INNOCUOUSTHREADGROUP = new ThreadGroup(root, "InnocuousThreadGroup"); + } else { + INNOCUOUSTHREADGROUP = AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public ThreadGroup run() { + return new ThreadGroup(root, "InnocuousThreadGroup"); + } + }); + } } catch (Exception e) { throw new Error(e); } diff --git a/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java b/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java index 14eba5aceef..a0245f0e4a9 100644 --- a/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java +++ b/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -432,11 +432,27 @@ private ImageLocation findImageLocation(String name) throws IOException { } } + /** + * Returns {@code true} if the given resource exists, {@code false} + * if not found. + */ + private boolean containsImageLocation(String name) throws IOException { + Objects.requireNonNull(name); + if (closed) + throw new IOException("ModuleReader is closed"); + ImageReader imageReader = SystemImage.reader(); + if (imageReader != null) { + return imageReader.verifyLocation(module, name); + } else { + // not an images build + return false; + } + } + @Override public Optional find(String name) throws IOException { - ImageLocation location = findImageLocation(name); - if (location != null) { - URI u = URI.create("jrt:/" + module + "/" + name); + if (containsImageLocation(name)) { + URI u = JNUA.create("jrt", "/" + module + "/" + name); return Optional.of(u); } else { return Optional.empty(); diff --git a/src/java.base/share/classes/jdk/internal/ref/CleanerFactory.java b/src/java.base/share/classes/jdk/internal/ref/CleanerFactory.java index e55e9d6378e..ab5f042de97 100644 --- a/src/java.base/share/classes/jdk/internal/ref/CleanerFactory.java +++ b/src/java.base/share/classes/jdk/internal/ref/CleanerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,8 +28,6 @@ import jdk.internal.misc.InnocuousThread; import java.lang.ref.Cleaner; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.concurrent.ThreadFactory; /** @@ -42,14 +40,8 @@ public final class CleanerFactory { private final static Cleaner commonCleaner = Cleaner.create(new ThreadFactory() { @Override public Thread newThread(Runnable r) { - return AccessController.doPrivileged(new PrivilegedAction<>() { - @Override - public Thread run() { - Thread t = InnocuousThread.newSystemThread("Common-Cleaner", r); - t.setPriority(Thread.MAX_PRIORITY - 2); - return t; - } - }); + return InnocuousThread.newSystemThread("Common-Cleaner", + r, Thread.MAX_PRIORITY - 2); } }); diff --git a/src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java b/src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java index 60924e19774..535e1cdcca4 100644 --- a/src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java +++ b/src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java @@ -213,15 +213,8 @@ static ThreadFactory factory() { final AtomicInteger cleanerThreadNumber = new AtomicInteger(); public Thread newThread(Runnable r) { - return AccessController.doPrivileged(new PrivilegedAction<>() { - @Override - public Thread run() { - Thread t = InnocuousThread.newThread(r); - t.setPriority(Thread.MAX_PRIORITY - 2); - t.setName("Cleaner-" + cleanerThreadNumber.getAndIncrement()); - return t; - } - }); + return InnocuousThread.newThread("Cleaner-" + cleanerThreadNumber.getAndIncrement(), + r, Thread.MIN_PRIORITY - 2); } } diff --git a/src/java.base/share/classes/jdk/internal/util/Preconditions.java b/src/java.base/share/classes/jdk/internal/util/Preconditions.java index 75777a6d1f0..0a8d7016b24 100644 --- a/src/java.base/share/classes/jdk/internal/util/Preconditions.java +++ b/src/java.base/share/classes/jdk/internal/util/Preconditions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -203,13 +203,13 @@ private static String outOfBoundsMessage(String checkKind, List= 0) ? String.valueOf(pathLen) : " undefined") + + "\n PathLen:" + pathLenAsString + "\n]\n"; } diff --git a/src/java.base/share/man/java.1 b/src/java.base/share/man/java.1 index 8dddc7e1b14..070ba40d8e0 100644 --- a/src/java.base/share/man/java.1 +++ b/src/java.base/share/man/java.1 @@ -22,7 +22,7 @@ .\"t .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JAVA" "1" "2020" "JDK 17" "JDK Commands" +.TH "JAVA" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/java.base/share/man/keytool.1 b/src/java.base/share/man/keytool.1 index 8067f45fdd2..70659fa119a 100644 --- a/src/java.base/share/man/keytool.1 +++ b/src/java.base/share/man/keytool.1 @@ -22,7 +22,7 @@ .\"t .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "KEYTOOL" "1" "2020" "JDK 16" "JDK Commands" +.TH "KEYTOOL" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/java.base/share/native/libjava/ClassLoader.c b/src/java.base/share/native/libjava/ClassLoader.c index 021a5a191eb..5f556ff902c 100644 --- a/src/java.base/share/native/libjava/ClassLoader.c +++ b/src/java.base/share/native/libjava/ClassLoader.c @@ -262,6 +262,9 @@ Java_java_lang_ClassLoader_defineClass0(JNIEnv *env, result = JVM_LookupDefineClass(env, lookup, utfName, body, length, pd, initialize, flags, classData); + if (utfName && utfName != buf) + free(utfName); + free_body: free(body); return result; diff --git a/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java b/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java index 62a93995b8d..b9a33a6e4c8 100644 --- a/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java +++ b/src/java.base/windows/classes/java/net/DefaultDatagramSocketImplFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,10 +97,9 @@ static DatagramSocketImpl createDatagramSocketImpl(boolean isMulticast) throw new SocketException("can't instantiate DatagramSocketImpl"); } } else { - if (!preferIPv4Stack && !isMulticast) - return new DualStackPlainDatagramSocketImpl(exclusiveBind); - else - return new TwoStacksPlainDatagramSocketImpl(exclusiveBind && !isMulticast, isMulticast); + // Always use TwoStacksPlainDatagramSocketImpl since we need + // to support multicasting at DatagramSocket level + return new TwoStacksPlainDatagramSocketImpl(exclusiveBind && !isMulticast, isMulticast); } } } diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsConstants.java b/src/java.base/windows/classes/sun/nio/fs/WindowsConstants.java index 5180fbe32d5..6fa8201cca9 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsConstants.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsConstants.java @@ -73,6 +73,7 @@ private WindowsConstants() { } // reparse point/symbolic link related constants public static final int IO_REPARSE_TAG_SYMLINK = 0xA000000C; + public static final int IO_REPARSE_TAG_AF_UNIX = 0x80000023; public static final int MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024; public static final int SYMBOLIC_LINK_FLAG_DIRECTORY = 0x1; public static final int SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 0x2; @@ -107,6 +108,7 @@ private WindowsConstants() { } public static final int ERROR_NOTIFY_ENUM_DIR = 1022; public static final int ERROR_PRIVILEGE_NOT_HELD = 1314; public static final int ERROR_NONE_MAPPED = 1332; + public static final int ERROR_CANT_ACCESS_FILE = 1920; public static final int ERROR_NOT_A_REPARSE_POINT = 4390; public static final int ERROR_INVALID_REPARSE_DATA = 4392; diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java b/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java index ab29229ceef..7202f532be7 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileAttributes.java @@ -431,6 +431,10 @@ public boolean isSymbolicLink() { return reparseTag == IO_REPARSE_TAG_SYMLINK; } + boolean isUnixDomainSocket() { + return reparseTag == IO_REPARSE_TAG_AF_UNIX; + } + @Override public boolean isDirectory() { // ignore FILE_ATTRIBUTE_DIRECTORY attribute if file is a sym link diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java b/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java index 2fe40b78204..30769680dc1 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileCopy.java @@ -139,6 +139,12 @@ static void copy(final WindowsPath source, sm.checkPermission(new LinkPermission("symbolic")); } + // if source is a Unix domain socket, we don't want to copy it for various + // reasons including consistency with Unix + if (sourceAttrs.isUnixDomainSocket()) { + throw new IOException("Can not copy socket file"); + } + final String sourcePath = asWin32Path(source); final String targetPath = asWin32Path(target); 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 14b36305dba..f380267adff 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java @@ -334,6 +334,13 @@ private void checkReadAccess(WindowsPath file) throws IOException { 0L); fc.close(); } catch (WindowsException exc) { + try { + if (exc.lastError() == ERROR_CANT_ACCESS_FILE && isUnixDomainSocket(file)) { + // socket file is accessible + return; + } + } catch (WindowsException ignore) {} + // Windows errors are very inconsistent when the file is a directory // (ERROR_PATH_NOT_FOUND returned for root directories for example) // so we retry by attempting to open it as a directory. @@ -346,6 +353,11 @@ private void checkReadAccess(WindowsPath file) throws IOException { } } + private static boolean isUnixDomainSocket(WindowsPath path) throws WindowsException { + WindowsFileAttributes attrs = WindowsFileAttributes.get(path, false); + return attrs.isUnixDomainSocket(); + } + @Override public void checkAccess(Path obj, AccessMode... modes) throws IOException { WindowsPath file = WindowsPath.toWindowsPath(obj); diff --git a/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java b/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java index 4b6e9068f48..eac4695b0cc 100644 --- a/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java +++ b/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java @@ -831,12 +831,52 @@ long openForReadAttributeAccess(boolean followLinks) int flags = FILE_FLAG_BACKUP_SEMANTICS; if (!followLinks) flags |= FILE_FLAG_OPEN_REPARSE_POINT; + try { + return openFileForReadAttributeAccess(flags); + } catch (WindowsException e) { + if (followLinks && e.lastError() == ERROR_CANT_ACCESS_FILE) { + // Object could be a Unix domain socket + try { + return openSocketForReadAttributeAccess(); + } catch (WindowsException ignore) {} + } + throw e; + } + } + + private long openFileForReadAttributeAccess(int flags) + throws WindowsException + { return CreateFile(getPathForWin32Calls(), - FILE_READ_ATTRIBUTES, - (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), - 0L, - OPEN_EXISTING, - flags); + FILE_READ_ATTRIBUTES, + (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), + 0L, + OPEN_EXISTING, + flags); + } + + /** + * Returns a handle to the file if it is a socket. + * Throws WindowsException if file is not a socket + */ + private long openSocketForReadAttributeAccess() + throws WindowsException + { + // needs to specify FILE_FLAG_OPEN_REPARSE_POINT if the file is a socket + int flags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT; + + long handle = openFileForReadAttributeAccess(flags); + + try { + WindowsFileAttributes attrs = WindowsFileAttributes.readAttributes(handle); + if (!attrs.isUnixDomainSocket()) { + throw new WindowsException("not a socket"); + } + return handle; + } catch (WindowsException e) { + CloseHandle(handle); + throw e; + } } void checkRead() { diff --git a/src/java.base/windows/native/libjava/WinNTFileSystem_md.c b/src/java.base/windows/native/libjava/WinNTFileSystem_md.c index faa015f17cc..adab62ac0c3 100644 --- a/src/java.base/windows/native/libjava/WinNTFileSystem_md.c +++ b/src/java.base/windows/native/libjava/WinNTFileSystem_md.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "jni.h" #include "io_util.h" @@ -187,6 +188,60 @@ static BOOL getFileInformation(const WCHAR *path, return result; } +/** + * path is likely to be a Unix domain socket. + * Verify and if it is return its attributes + */ +static DWORD getFinalAttributesUnixSocket(const WCHAR *path) +{ + DWORD result; + BY_HANDLE_FILE_INFORMATION finfo; + REPARSE_GUID_DATA_BUFFER reparse; + + HANDLE h = CreateFileW(path, + FILE_READ_ATTRIBUTES, + FILE_SHARE_DELETE | + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | + FILE_FLAG_OPEN_REPARSE_POINT, + NULL); + + if (h == INVALID_HANDLE_VALUE) + return INVALID_FILE_ATTRIBUTES; + + + if (!GetFileInformationByHandle(h, &finfo)) { + DWORD error = GetLastError(); + if (CloseHandle(h)) { + SetLastError(error); + } + return INVALID_FILE_ATTRIBUTES; + } + + if ((finfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) { + CloseHandle(h); + return INVALID_FILE_ATTRIBUTES; + } + + /* check the reparse tag */ + + if (DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, &reparse, + (DWORD)sizeof(reparse), &result, NULL) == 0) { + CloseHandle(h); + return INVALID_FILE_ATTRIBUTES; + } + + if (reparse.ReparseTag != IO_REPARSE_TAG_AF_UNIX) { + CloseHandle(h); + return INVALID_FILE_ATTRIBUTES; + } + + CloseHandle(h); + return finfo.dwFileAttributes; +} + /** * If the given attributes are the attributes of a reparse point, then * read and return the attributes of the special cases. @@ -217,6 +272,11 @@ DWORD getFinalAttributes(WCHAR *path) if (GetFileAttributesExW(path, GetFileExInfoStandard, &wfad)) { attr = getFinalAttributesIfReparsePoint(path, wfad.dwFileAttributes); + if (attr == INVALID_FILE_ATTRIBUTES) { + if (GetLastError() == ERROR_CANT_ACCESS_FILE) { + attr = getFinalAttributesUnixSocket(path); + } + } } else { DWORD lerr = GetLastError(); if ((lerr == ERROR_SHARING_VIOLATION || lerr == ERROR_ACCESS_DENIED) && diff --git a/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c b/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c index af033676815..1869009a1f9 100644 --- a/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c +++ b/src/java.base/windows/native/libnio/ch/UnixDomainSockets.c @@ -92,16 +92,7 @@ Java_sun_nio_ch_UnixDomainSockets_socketSupported(JNIEnv *env, jclass cl) return JNI_FALSE; } closesocket(s); - - /* Check for build 18362 or newer, due to Windows bug described in 8259014 */ - - OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 }; - DWORDLONG cond_mask = 0; - - VER_SET_CONDITION(cond_mask, VER_BUILDNUMBER, VER_GREATER_EQUAL); - osvi.dwBuildNumber = 18362; // Windows 10 (1903) or newer - - return VerifyVersionInfoW(&osvi, VER_BUILDNUMBER, cond_mask) != 0; + return JNI_TRUE; } JNIEXPORT jint JNICALL diff --git a/src/java.compiler/share/classes/javax/lang/model/element/Modifier.java b/src/java.compiler/share/classes/javax/lang/model/element/Modifier.java index afb6b4eb57e..0a237746084 100644 --- a/src/java.compiler/share/classes/javax/lang/model/element/Modifier.java +++ b/src/java.compiler/share/classes/javax/lang/model/element/Modifier.java @@ -64,10 +64,10 @@ public enum Modifier { */ DEFAULT, /** - * The modifier {@code value} - * @since 1.11 + * The modifier {@code primitive} + * @since 1.17 */ - VALUE, + PRIMITIVE, /** The modifier {@code static} */ STATIC, diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java index 5f6a076c755..3a9ed6b12f5 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaButtonLabeledUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -169,7 +169,13 @@ public synchronized void paint(final Graphics g, final JComponent c) { altIcon = b.getIcon(); } - altIcon.paintIcon(c, g, iconRect.x, iconRect.y); + int offset = 0; + if (b.isFocusOwner()) { + offset = 2; + altIcon = AquaFocus.createFocusedIcon(altIcon, c, 2); + } + + altIcon.paintIcon(c, g, iconRect.x - offset, iconRect.y - offset); } // Draw the Text diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m index 716c86527f0..8333ff48972 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m @@ -29,7 +29,6 @@ #import "JNIUtilities.h" -#import #import #import diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTSurfaceLayers.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTSurfaceLayers.m index c397dbf1f38..1a5dcb03b99 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTSurfaceLayers.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTSurfaceLayers.m @@ -28,7 +28,6 @@ #import "LWCToolkit.h" #import "JNIUtilities.h" -#import #import @implementation AWTSurfaceLayers diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m index eb5dae3c272..3afe59f697b 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m @@ -35,7 +35,6 @@ #import "JNIUtilities.h" #import -#import // keyboard layout static NSString *kbdLayout; @@ -135,7 +134,7 @@ - (void) viewDidMoveToWindow { [AWTToolkit eventCountPlusPlus]; - [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^() { + [ThreadUtilities performOnMainThreadWaiting:NO block:^() { [[self window] makeFirstResponder: self]; }]; if ([self window] != NULL) { @@ -461,8 +460,8 @@ -(void) deliverJavaKeyEventHelper: (NSEvent *) event { jstring characters = NULL; jstring charactersIgnoringModifiers = NULL; if ([event type] != NSFlagsChanged) { - characters = JNFNSToJavaString(env, [event characters]); - charactersIgnoringModifiers = JNFNSToJavaString(env, [event charactersIgnoringModifiers]); + characters = NSStringToJavaString(env, [event characters]); + charactersIgnoringModifiers = NSStringToJavaString(env, [event charactersIgnoringModifiers]); } DECLARE_CLASS(jc_NSEvent, "sun/lwawt/macosx/NSEvent"); @@ -575,10 +574,7 @@ - (jobject)awtComponent:(JNIEnv*)env DECLARE_FIELD_RETURN(jf_Peer, jc_CPlatformView, "peer", "Lsun/lwawt/LWWindowPeer;", NULL); if ((env == NULL) || (m_cPlatformView == NULL)) { NSLog(@"Apple AWT : Error AWTView:awtComponent given bad parameters."); - if (env != NULL) - { - JNFDumpJavaStack(env); - } + NSLog(@"%@",[NSThread callStackSymbols]); return NULL; } @@ -592,7 +588,7 @@ - (jobject)awtComponent:(JNIEnv*)env DECLARE_FIELD_RETURN(jf_Target, jc_LWWindowPeer, "target", "Ljava/awt/Component;", NULL); if (peer == NULL) { NSLog(@"Apple AWT : Error AWTView:awtComponent got null peer from CPlatformView"); - JNFDumpJavaStack(env); + NSLog(@"%@",[NSThread callStackSymbols]); return NULL; } jobject comp = (*env)->GetObjectField(env, peer, jf_Target); @@ -989,8 +985,8 @@ - (void) insertText:(id)aString replacementRange:(NSRange)replacementRange } DECLARE_METHOD(jm_insertText, jc_CInputMethod, "insertText", "(Ljava/lang/String;)V"); - jstring insertedText = JNFNSToJavaString(env, useString); - (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_insertText, insertedText); // AWT_THREADING Safe (AWTRunLoopMode) + jstring insertedText = NSStringToJavaString(env, useString); + (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_insertText, insertedText); CHECK_EXCEPTION(); (*env)->DeleteLocalRef(env, insertedText); @@ -1055,8 +1051,8 @@ - (void) setMarkedText:(id)aString selectedRange:(NSRange)selectionRange replace // NSInputContext already did the analysis of the TSM event and created attributes indicating // the underlining and color that should be done to the string. We need to look at the underline // style and color to determine what kind of Java hilighting needs to be done. - jstring inProcessText = JNFNSToJavaString(env, incomingString); - (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_startIMUpdate, inProcessText); // AWT_THREADING Safe (AWTRunLoopMode) + jstring inProcessText = NSStringToJavaString(env, incomingString); + (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_startIMUpdate, inProcessText); CHECK_EXCEPTION(); (*env)->DeleteLocalRef(env, inProcessText); @@ -1081,7 +1077,7 @@ - (void) setMarkedText:(id)aString selectedRange:(NSRange)selectionRange replace isGray = !([underlineColorObj isEqual:[NSColor blackColor]]); (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_addAttribute, isThickUnderline, - isGray, effectiveRange.location, effectiveRange.length); // AWT_THREADING Safe (AWTRunLoopMode) + isGray, effectiveRange.location, effectiveRange.length); CHECK_EXCEPTION(); } } @@ -1096,7 +1092,7 @@ - (void) setMarkedText:(id)aString selectedRange:(NSRange)selectionRange replace } (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_dispatchText, - selectionRange.location, selectionRange.length, JNI_FALSE); // AWT_THREADING Safe (AWTRunLoopMode) + selectionRange.location, selectionRange.length, JNI_FALSE); CHECK_EXCEPTION(); // If the marked text is being cleared (zero-length string) don't handle the key event. if ([incomingString length] == 0) { @@ -1118,7 +1114,7 @@ - (void) unmarkText JNIEnv *env = [ThreadUtilities getJNIEnv]; GET_CIM_CLASS(); DECLARE_METHOD(jm_unmarkText, jc_CInputMethod, "unmarkText", "()V"); - (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_unmarkText); // AWT_THREADING Safe (AWTRunLoopMode) + (*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_unmarkText); CHECK_EXCEPTION(); } @@ -1171,10 +1167,10 @@ - (NSAttributedString *) attributedSubstringForProposedRange:(NSRange)theRange a JNIEnv *env = [ThreadUtilities getJNIEnv]; DECLARE_METHOD_RETURN(jm_substringFromRange, jc_CInputMethod, "attributedSubstringFromRange", "(II)Ljava/lang/String;", nil); - jobject theString = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_substringFromRange, theRange.location, theRange.length); // AWT_THREADING Safe (AWTRunLoopMode) + jobject theString = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_substringFromRange, theRange.location, theRange.length); CHECK_EXCEPTION_NULL_RETURN(theString, nil); - id result = [[[NSAttributedString alloc] initWithString:JNFJavaToNSString(env, theString)] autorelease]; + id result = [[[NSAttributedString alloc] initWithString:JavaStringToNSString(env, theString)] autorelease]; #ifdef IM_DEBUG NSLog(@"attributedSubstringFromRange returning \"%@\"", result); #endif // IM_DEBUG @@ -1205,7 +1201,7 @@ - (NSRange) markedRange GET_CIM_CLASS_RETURN(range); DECLARE_METHOD_RETURN(jm_markedRange, jc_CInputMethod, "markedRange", "()[I", range); - array = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_markedRange); // AWT_THREADING Safe (AWTRunLoopMode) + array = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_markedRange); CHECK_EXCEPTION(); if (array) { @@ -1246,7 +1242,7 @@ - (NSRange) selectedRange fprintf(stderr, "AWTView InputMethod Selector Called : [selectedRange]\n"); #endif // IM_DEBUG - array = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_selectedRange); // AWT_THREADING Safe (AWTRunLoopMode) + array = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_selectedRange); CHECK_EXCEPTION(); if (array) { _array = (*env)->GetIntArrayElements(env, array, &isCopy); @@ -1285,7 +1281,7 @@ - (NSRect) firstRectForCharacterRange:(NSRange)theRange actualRange:(NSRangePoin #endif // IM_DEBUG array = (*env)->CallObjectMethod(env, fInputMethodLOCKABLE, jm_firstRectForCharacterRange, - theRange.location); // AWT_THREADING Safe (AWTRunLoopMode) + theRange.location); CHECK_EXCEPTION(); _array = (*env)->GetIntArrayElements(env, array, &isCopy); @@ -1326,7 +1322,7 @@ - (NSUInteger)characterIndexForPoint:(NSPoint)thePoint #endif // IM_DEBUG jint index = (*env)->CallIntMethod(env, fInputMethodLOCKABLE, jm_characterIndexForPoint, - (jint)flippedLocation.x, (jint)flippedLocation.y); // AWT_THREADING Safe (AWTRunLoopMode) + (jint)flippedLocation.x, (jint)flippedLocation.y); CHECK_EXCEPTION(); #ifdef IM_DEBUG diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m index bc682ed7ef6..33fde46c3fe 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m @@ -24,7 +24,6 @@ */ #import -#import #import "sun_lwawt_macosx_CPlatformWindow.h" #import "com_apple_eawt_event_GestureHandler.h" @@ -1444,7 +1443,7 @@ + (AWTWindow *) lastKeyWindow { NSWindow *nsWindow = OBJC(windowPtr); [nsWindow performSelectorOnMainThread:@selector(setTitle:) - withObject:JNFJavaToNSString(env, jtitle) + withObject:JavaStringToNSString(env, jtitle) waitUntilDone:NO]; JNI_COCOA_EXIT(env); @@ -1520,7 +1519,7 @@ + (AWTWindow *) lastKeyWindow { JNI_COCOA_ENTER(env); NSWindow *nsWindow = OBJC(windowPtr); - NSURL *url = (filename == NULL) ? nil : [NSURL fileURLWithPath:JNFNormalizedNSStringForPath(env, filename)]; + NSURL *url = (filename == NULL) ? nil : [NSURL fileURLWithPath:NormalizedPathNSStringFromJavaString(env, filename)]; [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ [nsWindow setRepresentedURL:url]; }]; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/ApplicationDelegate.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/ApplicationDelegate.m index 539f04dd090..590ed56e0c6 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/ApplicationDelegate.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/ApplicationDelegate.m @@ -32,8 +32,6 @@ #import "com_apple_eawt__AppMenuBarHandler.h" #import "com_apple_eawt__AppMiscHandlers.h" -#import - #import "CPopupMenu.h" #import "CMenuBar.h" #import "ThreadUtilities.h" @@ -290,10 +288,10 @@ - (void)_handleOpenURLEvent:(NSAppleEventDescriptor *)openURLEvent withReplyEven //fprintf(stderr,"jm_handleOpenURL\n"); JNIEnv *env = [ThreadUtilities getJNIEnv]; - jstring jURL = JNFNSToJavaString(env, url); + jstring jURL = NSStringToJavaString(env, url); GET_APPEVENTHANDLER_CLASS(); DECLARE_STATIC_METHOD(jm_handleOpenURI, sjc_AppEventHandler, "handleOpenURI", "(Ljava/lang/String;)V"); - (*env)->CallStaticVoidMethod(env, sjc_AppEventHandler, jm_handleOpenURI, jURL); // AWT_THREADING Safe (event) + (*env)->CallStaticVoidMethod(env, sjc_AppEventHandler, jm_handleOpenURI, jURL); CHECK_EXCEPTION(); (*env)->DeleteLocalRef(env, jURL); @@ -312,11 +310,11 @@ - (jobject)_createFilePathArrayFrom:(NSArray *)filenames withEnv:(JNIEnv *)env { DECLARE_METHOD_RETURN(jm_ArrayList_ctor, sjc_ArrayList, "", "(I)V", NULL); DECLARE_METHOD_RETURN(jm_ArrayList_add, sjc_ArrayList, "add", "(Ljava/lang/Object;)Z", NULL); - jobject jFileNamesArray = (*env)->NewObject(env, sjc_ArrayList, jm_ArrayList_ctor, (jint)[filenames count]); // AWT_THREADING Safe (known object) + jobject jFileNamesArray = (*env)->NewObject(env, sjc_ArrayList, jm_ArrayList_ctor, (jint)[filenames count]); CHECK_EXCEPTION_NULL_RETURN(jFileNamesArray, NULL); for (NSString *filename in filenames) { - jstring jFileName = JNFNormalizedJavaStringForPath(env, filename); + jstring jFileName = NormalizedPathJavaStringFromNSString(env, filename); (*env)->CallVoidMethod(env, jFileNamesArray, jm_ArrayList_add, jFileName); CHECK_EXCEPTION(); } @@ -338,7 +336,7 @@ - (void)application:(NSApplication *)theApplication openFiles:(NSArray *)fileNam // if these files were opened from a Spotlight query, try to get the search text from the current AppleEvent NSAppleEventDescriptor *currentEvent = [[NSAppleEventManager sharedAppleEventManager] currentAppleEvent]; NSString *searchString = [[currentEvent paramDescriptorForKeyword:keyAESearchText] stringValue]; - jstring jSearchString = JNFNSToJavaString(env, searchString); + jstring jSearchString = NSStringToJavaString(env, searchString); // convert the file names array jobject jFileNamesArray = [self _createFilePathArrayFrom:fileNames withEnv:env]; @@ -365,7 +363,7 @@ - (NSApplicationPrintReply)application:(NSApplication *)application printFiles:( GET_APPEVENTHANDLER_CLASS_RETURN(NSPrintingCancelled); DECLARE_STATIC_METHOD_RETURN(jm_handlePrintFile, sjc_AppEventHandler, "handlePrintFiles", "(Ljava/util/List;)V", NSPrintingCancelled); - (*env)->CallStaticVoidMethod(env, sjc_AppEventHandler, jm_handlePrintFile, jFileNamesArray); // AWT_THREADING Safe (event) + (*env)->CallStaticVoidMethod(env, sjc_AppEventHandler, jm_handlePrintFile, jFileNamesArray); CHECK_EXCEPTION(); (*env)->DeleteLocalRef(env, jFileNamesArray); @@ -380,7 +378,7 @@ + (void)_notifyJava:(jint)notificationType { JNIEnv *env = [ThreadUtilities getJNIEnv]; GET_APPEVENTHANDLER_CLASS(); DECLARE_STATIC_METHOD(jm_handleNativeNotification, sjc_AppEventHandler, "handleNativeNotification", "(I)V"); - (*env)->CallStaticVoidMethod(env, sjc_AppEventHandler, jm_handleNativeNotification, notificationType); // AWT_THREADING Safe (event) + (*env)->CallStaticVoidMethod(env, sjc_AppEventHandler, jm_handleNativeNotification, notificationType); CHECK_EXCEPTION(); } @@ -624,7 +622,7 @@ + (NSImage *)_dockIconImage { [ThreadUtilities performOnMainThread:@selector(_registerForNotification:) on:[ApplicationDelegate class] withObject:[NSNumber numberWithInt:notificationType] - waitUntilDone:NO]; // AWT_THREADING Safe (non-blocking) + waitUntilDone:NO]; JNI_COCOA_EXIT(env); } @@ -714,7 +712,7 @@ + (NSImage *)_dockIconImage { { JNI_COCOA_ENTER(env); - NSString *badgeString = JNFJavaToNSString(env, badge); + NSString *badgeString = JavaStringToNSString(env, badge); [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ NSDockTile *dockTile = [NSApp dockTile]; [dockTile setBadgeLabel:badgeString]; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m index 3a6d573579c..896e11cf568 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CClipboard.m @@ -27,7 +27,6 @@ #import "ThreadUtilities.h" #import "JNIUtilities.h" #import -#import @interface CClipboard : NSObject { } @property NSInteger changeCount; @@ -99,7 +98,7 @@ - (void)checkPasteboard:(id)sender { DECLARE_METHOD(jm_lostOwnership, jc_CClipboard, "notifyLostOwnership", "()V"); @synchronized(self) { if (self.clipboardOwner) { - (*env)->CallVoidMethod(env, self.clipboardOwner, jm_lostOwnership); // AWT_THREADING Safe (event) + (*env)->CallVoidMethod(env, self.clipboardOwner, jm_lostOwnership); CHECK_EXCEPTION(); (*env)->DeleteGlobalRef(env, self.clipboardOwner); self.clipboardOwner = NULL; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CCursorManager.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CCursorManager.m index e3d054296cd..99727a3f9fd 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CCursorManager.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CCursorManager.m @@ -26,7 +26,6 @@ #include "sun_lwawt_macosx_CCursorManager.h" #include -#include #include "GeomUtilities.h" #include "ThreadUtilities.h" @@ -75,7 +74,7 @@ static void setCursorOnAppKitThread(NSCursor *cursor) { { JNI_COCOA_ENTER(env); - NSString *cursorName = JNFJavaToNSString(env, name); + NSString *cursorName = JavaStringToNSString(env, name); SEL cursorSelector = (type == sun_lwawt_macosx_CCursorManager_NAMED_CURSOR) ? lookupCursorSelectorForName(cursorName) : lookupCursorSelectorForType(type); if (cursorSelector == nil) { NSString *reason = [NSString stringWithFormat:@"unimplemented built-in cursor type: %d / %@", type, cursorName]; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDataTransferer.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDataTransferer.m index 80812bf4be4..f0bc347197f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDataTransferer.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDataTransferer.m @@ -28,9 +28,6 @@ #import "JNIUtilities.h" -#import - - // ***** NOTE ***** This dictionary corresponds to the static array predefinedClipboardNames // in CDataTransferer.java. NSMutableDictionary *sStandardMappings = nil; @@ -110,7 +107,7 @@ jlong registerFormatWithPasteboard(NSString *format) { { jlong returnValue = -1; JNI_COCOA_ENTER(env); - returnValue = registerFormatWithPasteboard(JNFJavaToNSString(env, newformat)); + returnValue = registerFormatWithPasteboard(JavaStringToNSString(env, newformat)); JNI_COCOA_EXIT(env); return returnValue; } @@ -125,7 +122,7 @@ jlong registerFormatWithPasteboard(NSString *format) { { jstring returnValue = NULL; JNI_COCOA_ENTER(env); - returnValue = JNFNSToJavaString(env, formatForIndex(index)); + returnValue = NSStringToJavaString(env, formatForIndex(index)); JNI_COCOA_EXIT(env); return returnValue; } @@ -138,7 +135,7 @@ static jobjectArray CreateJavaFilenameArray(JNIEnv *env, NSArray *filenameArray) // Get the java.lang.String class object: jclass stringClazz = (*env)->FindClass(env, "java/lang/String"); CHECK_NULL_RETURN(stringClazz, nil); - jobject jfilenameArray = (*env)->NewObjectArray(env, filenameCount, stringClazz, NULL); // AWT_THREADING Safe (known object) + jobject jfilenameArray = (*env)->NewObjectArray(env, filenameCount, stringClazz, NULL); if ((*env)->ExceptionOccurred(env)) { (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDesktopPeer.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDesktopPeer.m index 63ef7e4af8f..94d3e4efe54 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDesktopPeer.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDesktopPeer.m @@ -27,7 +27,6 @@ #import "JNIUtilities.h" #import #import -#import /* * Class: sun_lwawt_macosx_CDesktopPeer @@ -43,7 +42,7 @@ // I would love to use NSWorkspace here, but it's not thread safe. Why? I don't know. // So we use LaunchServices directly. - NSURL *url = [NSURL URLWithString:JNFJavaToNSString(env, uri)]; + NSURL *url = [NSURL URLWithString:JavaStringToNSString(env, uri)]; LSLaunchFlags flags = kLSLaunchDefaults; @@ -68,7 +67,7 @@ // I would love to use NSWorkspace here, but it's not thread safe. Why? I don't know. // So we use LaunchServices directly. - NSString *path = JNFNormalizedNSStringForPath(env, jpath); + NSString *path = NormalizedPathNSStringFromJavaString(env, jpath); NSURL *url = [NSURL fileURLWithPath:(NSString *)path]; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDragSource.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDragSource.m index fc9d855e086..fde95fc9d7f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDragSource.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDragSource.m @@ -28,7 +28,6 @@ #import "java_awt_dnd_DnDConstants.h" #import -#import #import "AWTEvent.h" #import "AWTView.h" @@ -572,7 +571,7 @@ - (void)doDrag GET_DSCP_CLASS(); DECLARE_METHOD(dragDropFinishedMethod, CDragSourceContextPeerClass, "dragDropFinished", "(ZIII)V"); DLog3(@" -> posting dragDropFinished, point %f, %f", point.x, point.y); - (*env)->CallVoidMethod(env, fDragSourceContextPeer, dragDropFinishedMethod, success, dragOp, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event) + (*env)->CallVoidMethod(env, fDragSourceContextPeer, dragDropFinishedMethod, success, dragOp, (jint) point.x, (jint) point.y); CHECK_EXCEPTION(); DECLARE_METHOD(resetHoveringMethod, CDragSourceContextPeerClass, "resetHovering", "()V"); (*env)->CallVoidMethod(env, fDragSourceContextPeer, resetHoveringMethod); // Hust reset static variable @@ -594,7 +593,7 @@ - (void)drag { AWT_ASSERT_NOT_APPKIT_THREAD; - [self performSelectorOnMainThread:@selector(doDrag) withObject:nil waitUntilDone:YES]; // AWT_THREADING Safe (called from unique asynchronous thread) + [self performSelectorOnMainThread:@selector(doDrag) withObject:nil waitUntilDone:YES]; } /******************************** BEGIN NSDraggingSource Interface ********************************/ @@ -613,7 +612,7 @@ - (void)draggingOperationChanged:(NSDragOperation)dragOp { GET_DSCP_CLASS(); DECLARE_METHOD(operationChangedMethod, CDragSourceContextPeerClass, "operationChanged", "(IIII)V"); - (*env)->CallVoidMethod(env, fDragSourceContextPeer, operationChangedMethod, targetActions, modifiedModifiers, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event) + (*env)->CallVoidMethod(env, fDragSourceContextPeer, operationChangedMethod, targetActions, modifiedModifiers, (jint) point.x, (jint) point.y); CHECK_EXCEPTION(); } @@ -688,11 +687,11 @@ - (void)draggedImage:(NSImage *)image movedTo:(NSPoint)screenPoint { DLog3(@" -> posting dragMotion, point %f, %f", point.x, point.y); GET_DSCP_CLASS(); DECLARE_METHOD(dragMotionMethod, CDragSourceContextPeerClass, "dragMotion", "(IIII)V"); - (*env)->CallVoidMethod(env, fDragSourceContextPeer, dragMotionMethod, targetActions, (jint) fModifiers, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event) + (*env)->CallVoidMethod(env, fDragSourceContextPeer, dragMotionMethod, targetActions, (jint) fModifiers, (jint) point.x, (jint) point.y); CHECK_EXCEPTION(); DLog3(@" -> posting dragMouseMoved, point %f, %f", point.x, point.y); DECLARE_METHOD(dragMouseMovedMethod, CDragSourceContextPeerClass, "dragMouseMoved", "(IIII)V"); - (*env)->CallVoidMethod(env, fDragSourceContextPeer, dragMouseMovedMethod, targetActions, (jint) fModifiers, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event) + (*env)->CallVoidMethod(env, fDragSourceContextPeer, dragMouseMovedMethod, targetActions, (jint) fModifiers, (jint) point.x, (jint) point.y); CHECK_EXCEPTION(); } JNI_COCOA_EXIT(env); @@ -719,7 +718,7 @@ - (void) postDragEnter { DLog3(@" -> posting dragEnter, point %f, %f", point.x, point.y); GET_DSCP_CLASS(); DECLARE_METHOD(dragEnterMethod, CDragSourceContextPeerClass, "dragEnter", "(IIII)V"); - (*env)->CallVoidMethod(env, fDragSourceContextPeer, dragEnterMethod, targetActions, (jint) fModifiers, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event) + (*env)->CallVoidMethod(env, fDragSourceContextPeer, dragEnterMethod, targetActions, (jint) fModifiers, (jint) point.x, (jint) point.y); CHECK_EXCEPTION(); } @@ -731,7 +730,7 @@ - (void) postDragExit { DLog3(@" -> posting dragExit, point %f, %f", point.x, point.y); GET_DSCP_CLASS(); DECLARE_METHOD(dragExitMethod, CDragSourceContextPeerClass, "dragExit", "(II)V"); - (*env)->CallVoidMethod(env, fDragSourceContextPeer, dragExitMethod, (jint) point.x, (jint) point.y); // AWT_THREADING Safe (event) + (*env)->CallVoidMethod(env, fDragSourceContextPeer, dragExitMethod, (jint) point.x, (jint) point.y); CHECK_EXCEPTION(); } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDragSourceContextPeer.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDragSourceContextPeer.m index 4b86ec6818d..0366f2b6d1e 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDragSourceContextPeer.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDragSourceContextPeer.m @@ -26,7 +26,6 @@ #import "sun_lwawt_macosx_CDragSourceContextPeer.h" #import "JNIUtilities.h" -#import #import "CDragSource.h" #import "ThreadUtilities.h" diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTarget.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTarget.m index a5540406411..e5f44b4a711 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTarget.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTarget.m @@ -31,7 +31,6 @@ #import "sun_lwawt_macosx_CDropTarget.h" #import "java_awt_dnd_DnDConstants.h" -#import #import #include diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTargetContextPeer.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTargetContextPeer.m index 8020706ae3b..2e590369508 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTargetContextPeer.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CDropTargetContextPeer.m @@ -25,8 +25,6 @@ #import "sun_lwawt_macosx_CDropTargetContextPeer.h" -#import - #import "CDataTransferer.h" #import "CDropTarget.h" #import "DnDUtilities.h" diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CFRetainedResource.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CFRetainedResource.m index c0ee841eb41..2759719888f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CFRetainedResource.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CFRetainedResource.m @@ -24,9 +24,9 @@ */ #import "JNIUtilities.h" +#import "ThreadUtilities.h" #import -#import #import "sun_lwawt_macosx_CFRetainedResource.h" @@ -49,7 +49,7 @@ }]; } else { // could happen if we are embedded inside SWT/FX application, - [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^() { + [ThreadUtilities performOnMainThreadWaiting:NO block:^() { CFRelease(jlong_to_ptr(ptr)); }]; } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CFileDialog.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/CFileDialog.h index ba435113eec..677c9715679 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CFileDialog.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CFileDialog.h @@ -24,7 +24,6 @@ */ #import -#import @interface CFileDialog : NSObject { // Should we query back to Java for a file filter? diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CFileDialog.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CFileDialog.m index 4b09d07114b..3b895be8094 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CFileDialog.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CFileDialog.m @@ -25,11 +25,10 @@ #import #import -#import -#import "CFileDialog.h" #import "ThreadUtilities.h" #import "JNIUtilities.h" +#import "CFileDialog.h" #import "java_awt_FileDialog.h" #import "sun_lwawt_macosx_CFileDialog.h" @@ -143,11 +142,11 @@ - (void)safeSaveOrLoad { - (BOOL) askFilenameFilter:(NSString *)filename { JNIEnv *env = [ThreadUtilities getJNIEnv]; - jstring jString = JNFNormalizedJavaStringForPath(env, filename); + jstring jString = NormalizedPathJavaStringFromNSString(env, filename); DECLARE_CLASS_RETURN(jc_CFileDialog, "sun/lwawt/macosx/CFileDialog", NO); DECLARE_METHOD_RETURN(jm_queryFF, jc_CFileDialog, "queryFilenameFilter", "(Ljava/lang/String;)Z", NO); - BOOL returnValue = (*env)->CallBooleanMethod(env, fFileDialog, jm_queryFF, jString); // AWT_THREADING Safe (AWTRunLoopMode) + BOOL returnValue = (*env)->CallBooleanMethod(env, fFileDialog, jm_queryFF, jString); CHECK_EXCEPTION(); (*env)->DeleteLocalRef(env, jString); @@ -199,7 +198,7 @@ - (NSArray *)URLs { jobjectArray returnValue = NULL; JNI_COCOA_ENTER(env); - NSString *dialogTitle = JNFJavaToNSString(env, title); + NSString *dialogTitle = JavaStringToNSString(env, title); if ([dialogTitle length] == 0) { dialogTitle = @" "; } @@ -207,15 +206,15 @@ - (NSArray *)URLs { CFileDialog *dialogDelegate = [[CFileDialog alloc] initWithFilter:hasFilter fileDialog:peer title:dialogTitle - directory:JNFJavaToNSString(env, directory) - file:JNFJavaToNSString(env, file) + directory:JavaStringToNSString(env, directory) + file:JavaStringToNSString(env, file) mode:mode multipleMode:multipleMode shouldNavigate:navigateApps canChooseDirectories:chooseDirectories withEnv:env]; - [JNFRunLoop performOnMainThread:@selector(safeSaveOrLoad) + [ThreadUtilities performOnMainThread:@selector(safeSaveOrLoad) on:dialogDelegate withObject:nil waitUntilDone:YES]; @@ -228,7 +227,7 @@ - (NSArray *)URLs { returnValue = (*env)->NewObjectArray(env, count, jc_String, NULL); [urls enumerateObjectsUsingBlock:^(id url, NSUInteger index, BOOL *stop) { - jstring filename = JNFNormalizedJavaStringForPath(env, [url path]); + jstring filename = NormalizedPathJavaStringFromNSString(env, [url path]); (*env)->SetObjectArrayElement(env, returnValue, index, filename); (*env)->DeleteLocalRef(env, filename); }]; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m index e82a20105dc..4ac03def230 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsDevice.m @@ -28,8 +28,6 @@ #include "GeomUtilities.h" #include "JNIUtilities.h" -#import - /** * Some default values for invalid CoreGraphics display ID. */ diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsEnv.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsEnv.m index 76dc31fa101..58338cbc6c1 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsEnv.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CGraphicsEnv.m @@ -28,8 +28,6 @@ #import "JNIUtilities.h" #import "ThreadUtilities.h" -#import - #define MAX_DISPLAYS 64 /* @@ -114,19 +112,18 @@ [ThreadUtilities performOnMainThreadWaiting:NO block:^() { - JNFPerformEnvBlock(JNFThreadDetachImmediately, ^(JNIEnv *env) { - jobject cgeRef = (jobject)userInfo; - - jobject graphicsEnv = (*env)->NewLocalRef(env, cgeRef); - if (graphicsEnv == NULL) return; // ref already GC'd - DECLARE_CLASS(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment"); - DECLARE_METHOD(jm_displayReconfiguration, - jc_CGraphicsEnvironment, "_displayReconfiguration","(IZ)V"); - (*env)->CallVoidMethod(env, graphicsEnv, jm_displayReconfiguration, - (jint) display, (jboolean) flags & kCGDisplayRemoveFlag); - (*env)->DeleteLocalRef(env, graphicsEnv); - CHECK_EXCEPTION(); - }); + JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; + jobject cgeRef = (jobject)userInfo; + + jobject graphicsEnv = (*env)->NewLocalRef(env, cgeRef); + if (graphicsEnv == NULL) return; // ref already GC'd + DECLARE_CLASS(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment"); + DECLARE_METHOD(jm_displayReconfiguration, + jc_CGraphicsEnvironment, "_displayReconfiguration","(IZ)V"); + (*env)->CallVoidMethod(env, graphicsEnv, jm_displayReconfiguration, + (jint) display, (jboolean) flags & kCGDisplayRemoveFlag); + (*env)->DeleteLocalRef(env, graphicsEnv); + CHECK_EXCEPTION(); }]; } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CImage.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CImage.m index 23daa3528a8..051588f95bf 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CImage.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CImage.m @@ -25,7 +25,6 @@ #import "jni_util.h" #import -#import #import "GeomUtilities.h" #import "ThreadUtilities.h" @@ -204,7 +203,7 @@ JNI_COCOA_ENTER(env); - NSString *path = JNFNormalizedNSStringForPath(env, file); + NSString *path = NormalizedPathNSStringFromJavaString(env, file); image = [[NSImage alloc] initByReferencingFile:path]; JNI_COCOA_EXIT(env); @@ -224,7 +223,7 @@ JNI_COCOA_ENTER(env); - NSString *path = JNFNormalizedNSStringForPath(env, file); + NSString *path = NormalizedPathNSStringFromJavaString(env, file); [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ image = [[[NSWorkspace sharedWorkspace] iconForFile:path] retain]; [image setScalesWhenResized:TRUE]; @@ -247,7 +246,7 @@ JNI_COCOA_ENTER(env); - image = [[NSImage imageNamed:JNFJavaToNSString(env, name)] retain]; + image = [[NSImage imageNamed:JavaStringToNSString(env, name)] retain]; JNI_COCOA_EXIT(env); diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CInputMethod.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CInputMethod.m index 3c5b18c5269..88585a6cbf7 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CInputMethod.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CInputMethod.m @@ -32,7 +32,6 @@ #import "AWTView.h" #import "JNIUtilities.h" -#import #import #define JAVA_LIST @"JAVA_LIST" @@ -160,7 +159,7 @@ + (void) _nativeEndComposition:(AWTView *)view { }]; if (keyboardInfo == nil) return NULL; - returnValue = JNFNSToJavaString(env, keyboardInfo); + returnValue = NSStringToJavaString(env, keyboardInfo); [keyboardInfo release]; JNI_COCOA_EXIT(env); @@ -259,7 +258,7 @@ + (void) _nativeEndComposition:(AWTView *)view { (JNIEnv *env, jobject this, jstring locale, jboolean isActivating) { JNI_COCOA_ENTER(env); - NSString *localeStr = JNFJavaToNSString(env, locale); + NSString *localeStr = JavaStringToNSString(env, locale); [localeStr retain]; [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenu.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenu.m index 59223045aa4..103176b9ca0 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenu.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenu.m @@ -23,7 +23,6 @@ * questions. */ -#import #import @@ -216,7 +215,7 @@ - (NSString *)description { { JNI_COCOA_ENTER(env); // Set the menu's title. - [((CMenu *)jlong_to_ptr(menuObject)) setJavaMenuTitle:JNFJavaToNSString(env, label)]; + [((CMenu *)jlong_to_ptr(menuObject)) setJavaMenuTitle:JavaStringToNSString(env, label)]; JNI_COCOA_EXIT(env); } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuBar.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuBar.m index 6c430f167f5..49a6a80da21 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuBar.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuBar.m @@ -26,7 +26,6 @@ #import "JNIUtilities.h" #import -#import #import diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuComponent.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuComponent.m index d49edec879e..ba802f801b8 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuComponent.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuComponent.m @@ -24,7 +24,6 @@ */ #import "CMenuComponent.h" -#import #import "ThreadUtilities.h" diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m index e0e4f4b169a..8e86dd46a79 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m @@ -23,7 +23,6 @@ * questions. */ -#import #include #import "CMenuItem.h" #import "CMenu.h" @@ -313,7 +312,7 @@ static unichar AWTKeyToMacShortcut(jint awtKey, BOOL doShift) { jchar shortcutKey, jint shortcutKeyCode, jint mods) { JNI_COCOA_ENTER(env); - NSString *theLabel = JNFJavaToNSString(env, label); + NSString *theLabel = JavaStringToNSString(env, label); NSString *theKeyEquivalent = nil; unichar macKey = shortcutKey; @@ -342,7 +341,7 @@ static unichar AWTKeyToMacShortcut(jint awtKey, BOOL doShift) { (JNIEnv *env, jobject peer, jlong menuItemObj, jstring tooltip) { JNI_COCOA_ENTER(env); - NSString *theTooltip = JNFJavaToNSString(env, tooltip); + NSString *theTooltip = JavaStringToNSString(env, tooltip); [((CMenuItem *)jlong_to_ptr(menuItemObj)) setJavaToolTipText:theTooltip]; JNI_COCOA_EXIT(env); } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CPopupMenu.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CPopupMenu.m index b77756dfaa4..11b9172707a 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CPopupMenu.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CPopupMenu.m @@ -24,7 +24,6 @@ */ #import -#import #import "AWTWindow.h" #import "AWTView.h" diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m index 51aa9a79e2c..db5c192c6c8 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CPrinterJob.m @@ -30,7 +30,6 @@ #import "sun_lwawt_macosx_CPrinterPageDialog.h" #import -#import #import "PrinterView.h" #import "PrintModel.h" @@ -87,7 +86,7 @@ NSPrintInfo* defaultPrintInfo = [[NSPrintInfo sharedPrintInfo] copy]; if (printer != NULL) { - NSPrinter* nsPrinter = [NSPrinter printerWithName:JNFJavaToNSString(env, printer)]; + NSPrinter* nsPrinter = [NSPrinter printerWithName:JavaStringToNSString(env, printer)]; if (nsPrinter != nil) { [defaultPrintInfo setPrinter:nsPrinter]; @@ -345,7 +344,7 @@ static void javaPageFormatToNSPrintInfo(JNIEnv* env, jobject srcPrintJob, jobjec jobject printerNameObj = (*env)->CallObjectMethod(env, srcPrintJob, jm_getPrinterName); CHECK_EXCEPTION(); if (printerNameObj == NULL) return; - NSString *printerName = JNFJavaToNSString(env, printerNameObj); + NSString *printerName = JavaStringToNSString(env, printerNameObj); if (printerName == nil) return; NSPrinter *printer = [NSPrinter printerWithName:printerName]; if (printer == nil) return; @@ -364,7 +363,7 @@ static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject d // get the selected printer's name, and set the appropriate PrintService on the Java side NSString *name = [[src printer] name]; - jstring printerName = JNFNSToJavaString(env, name); + jstring printerName = NSStringToJavaString(env, name); (*env)->CallVoidMethod(env, dstPrinterJob, jm_setService, printerName); CHECK_EXCEPTION(); @@ -375,7 +374,7 @@ static void nsPrintInfoToJavaPrinterJob(JNIEnv* env, NSPrintInfo* src, jobject d CHECK_EXCEPTION(); NSURL *url = [printingDictionary objectForKey:NSPrintJobSavingURL]; NSString *nsStr = [url absoluteString]; - jstring str = JNFNSToJavaString(env, nsStr); + jstring str = NSStringToJavaString(env, nsStr); (*env)->CallVoidMethod(env, dstPrinterJob, jm_setDestinationFile, str); CHECK_EXCEPTION(); } else { @@ -491,7 +490,7 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj CHECK_EXCEPTION(); if (dest != NULL) { [dst setJobDisposition:NSPrintSaveJob]; - NSString *nsDestStr = JNFJavaToNSString(env, dest); + NSString *nsDestStr = JavaStringToNSString(env, dest); NSURL *nsURL = [NSURL fileURLWithPath:nsDestStr isDirectory:NO]; [printingDictionary setObject:nsURL forKey:NSPrintJobSavingURL]; } else { @@ -628,7 +627,7 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj jobject printerTrayObj = (*env)->CallObjectMethod(env, jthis, jm_getPrinterTray); CHECK_EXCEPTION(); if (printerTrayObj != NULL) { - NSString *printerTray = JNFJavaToNSString(env, printerTrayObj); + NSString *printerTray = JavaStringToNSString(env, printerTrayObj); if (printerTray != nil) { [[printInfo printSettings] setObject:printerTray forKey:@"InputSlot"]; } @@ -642,7 +641,7 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj jobject printerNameObj = (*env)->CallObjectMethod(env, jthis, jm_getPrinterName); CHECK_EXCEPTION(); if (printerNameObj != NULL) { - NSString *printerName = JNFJavaToNSString(env, printerNameObj); + NSString *printerName = JavaStringToNSString(env, printerNameObj); if (printerName != nil) { NSPrinter *printer = [NSPrinter printerWithName:printerName]; if (printer != nil) [printInfo setPrinter:printer]; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m index 501d0f1886f..9d90086677d 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobot.m @@ -25,7 +25,6 @@ #import "JNIUtilities.h" -#import #import #import "CRobotKeyCode.h" diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CSystemColors.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CSystemColors.m index 2cfec904805..ca61907a868 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CSystemColors.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CSystemColors.m @@ -28,7 +28,6 @@ #import "java_awt_SystemColor.h" #import "sun_lwawt_macosx_LWCToolkit.h" -#import #import #import "ThreadUtilities.h" diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CTextPipe.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CTextPipe.m index 7c963d46e4e..c95ea3822d2 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CTextPipe.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CTextPipe.m @@ -30,8 +30,6 @@ #import "sun_lwawt_macosx_CTextPipe.h" #import "sun_java2d_OSXSurfaceData.h" -#import - #import "CoreTextSupport.h" #import "QuartzSurfaceData.h" #include "AWTStrike.h" @@ -586,6 +584,9 @@ render using the right font (see bug 7183516) when attribString is not JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CTextPipe_doDrawString (JNIEnv *env, jobject jthis, jobject jsurfacedata, jlong awtStrikePtr, jstring str, jdouble x, jdouble y) { + if (str == NULL) { + return; + } QuartzSDOps *qsdo = (QuartzSDOps *)SurfaceData_GetOps(env, jsurfacedata); AWTStrike *awtStrike = (AWTStrike *)jlong_to_ptr(awtStrikePtr); @@ -597,7 +598,7 @@ render using the right font (see bug 7183516) when attribString is not { jchar unichars[len]; (*env)->GetStringRegion(env, str, 0, len, unichars); - JNF_CHECK_AND_RETHROW_EXCEPTION(env); + CHECK_EXCEPTION(); // Draw the text context DrawTextContext(env, qsdo, awtStrike, unichars, len, x, y); @@ -605,12 +606,16 @@ render using the right font (see bug 7183516) when attribString is not else { // Get string to draw and the length - const jchar *unichars = JNFGetStringUTF16UniChars(env, str); + const jchar *unichars = (*env)->GetStringChars(env, str, NULL); + if (unichars == NULL) { + JNU_ThrowOutOfMemoryError(env, "Could not get string chars"); + return; + } // Draw the text context DrawTextContext(env, qsdo, awtStrike, unichars, len, x, y); - JNFReleaseStringUTF16UniChars(env, str, unichars); + (*env)->ReleaseStringChars(env, str, unichars); } JNI_COCOA_RENDERER_EXIT(env); @@ -635,7 +640,7 @@ render using the right font (see bug 7183516) when attribString is not { jchar copyUnichars[length]; (*env)->GetCharArrayRegion(env, unicodes, offset, length, copyUnichars); - JNF_CHECK_AND_RETHROW_EXCEPTION(env); + CHECK_EXCEPTION(); DrawTextContext(env, qsdo, awtStrike, copyUnichars, length, x, y); } else @@ -648,7 +653,7 @@ render using the right font (see bug 7183516) when attribString is not @try { (*env)->GetCharArrayRegion(env, unicodes, offset, length, copyUnichars); - JNF_CHECK_AND_RETHROW_EXCEPTION(env); + CHECK_EXCEPTION(); DrawTextContext(env, qsdo, awtStrike, copyUnichars, length, x, y); } @finally { free(copyUnichars); diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m index 9bd18de2eee..6d160ab0dbb 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m @@ -26,7 +26,6 @@ #import "jni_util.h" #import -#import #import "CTrayIcon.h" #import "ThreadUtilities.h" @@ -342,7 +341,7 @@ - (void) otherMouseDragged:(NSEvent *)event { JNI_COCOA_ENTER(env); AWTTrayIcon *icon = jlong_to_ptr(model); - NSString *tooltip = JNFJavaToNSString(env, jtooltip); + NSString *tooltip = JavaStringToNSString(env, jtooltip); [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ [icon setTooltip:tooltip]; }]; @@ -395,8 +394,8 @@ - (void) otherMouseDragged:(NSEvent *)event { JNI_COCOA_ENTER(env); AWTTrayIcon *icon = jlong_to_ptr(model); - NSString *caption = JNFJavaToNSString(env, jcaption); - NSString *text = JNFJavaToNSString(env, jtext); + NSString *caption = JavaStringToNSString(env, jcaption); + NSString *text = JavaStringToNSString(env, jtext); NSImage * contentImage = jlong_to_ptr(nsimage); [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/CWrapper.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/CWrapper.m index ca6580b2b0c..3244438bc1b 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/CWrapper.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/CWrapper.m @@ -25,7 +25,6 @@ #import "JNIUtilities.h" -#import #import "ThreadUtilities.h" #import "sun_lwawt_macosx_CWrapper_NSWindow.h" @@ -592,7 +591,7 @@ static void initLevels() JNI_COCOA_ENTER(env); NSView *view = (NSView *)jlong_to_ptr(viewPtr); - NSString* s = JNFJavaToNSString(env, msg); + NSString* s = JavaStringToNSString(env, msg); [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ [view setToolTip: s]; }]; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/GeomUtilities.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/GeomUtilities.m index 7f806ccef65..13ad3d7db6e 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/GeomUtilities.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/GeomUtilities.m @@ -24,7 +24,6 @@ */ #import "GeomUtilities.h" -#import static jobject NewJavaRect(JNIEnv *env, jdouble x, jdouble y, jdouble w, jdouble h) { DECLARE_CLASS_RETURN(sjc_Rectangle2DDouble, "java/awt/geom/Rectangle2D$Double", NULL); @@ -100,7 +99,10 @@ NSSize JavaToNSSize(JNIEnv *env, jobject dimension) { static NSScreen *primaryScreen(JNIEnv *env) { NSScreen *primaryScreen = [[NSScreen screens] objectAtIndex:0]; if (primaryScreen != nil) return primaryScreen; - if (env != NULL) [JNFException raise:env as:kRuntimeException reason:"Failed to convert, no screen."]; + if ((env != NULL) && ([NSThread isMainThread] == NO)) { + JNU_ThrowByName(env, "java/lang/RuntimeException", "Failed to convert, no screen."); + } + [NSException raise:NSGenericException format:@"Failed to convert, no screen."]; return nil; } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/ImageSurfaceData.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/ImageSurfaceData.m index bac3fbfa78e..47dcd3d5b2c 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/ImageSurfaceData.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/ImageSurfaceData.m @@ -32,7 +32,6 @@ #import "ThreadUtilities.h" #import "JNIUtilities.h" -#import #import "BufImgSurfaceData.h" diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m index 5fb8eeb8a69..03a5630b608 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityAction.m @@ -84,7 +84,7 @@ - (NSString *)getDescription fCompLocal ); CHECK_EXCEPTION(); if (jstr != NULL) { - str = JNFJavaToNSString(env, jstr); // AWT_THREADING Safe (AWTRunLoopMode) + str = JavaStringToNSString(env, jstr); (*env)->DeleteLocalRef(env, jstr); } (*env)->DeleteLocalRef(env, fCompLocal); @@ -100,7 +100,7 @@ - (void)perform "(Ljavax/accessibility/AccessibleAction;ILjava/awt/Component;)V"); (*env)->CallStaticVoidMethod(env, sjc_CAccessibility, jm_doAccessibleAction, - fAccessibleAction, fIndex, fComponent); // AWT_THREADING Safe (AWTRunLoopMode) + fAccessibleAction, fIndex, fComponent); CHECK_EXCEPTION(); } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.h index d1b692399df..f3dfe247ede 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.h @@ -23,7 +23,7 @@ * questions. */ -#import +#import "JNIUtilities.h" extern NSString *const JavaAccessibilityIgnore; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m index c22d7bf1e46..12817e63ecd 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaAccessibilityUtilities.m @@ -27,8 +27,6 @@ #import "JNIUtilities.h" #import -#import - static BOOL JavaAccessibilityIsSupportedAttribute(id element, NSString *attribute); static void JavaAccessibilityLogError(NSString *message); @@ -58,7 +56,7 @@ NSSize getAxComponentSize(JNIEnv *env, jobject axComponent, jobject component) DECLARE_STATIC_METHOD_RETURN(jm_getSize, sjc_CAccessibility, "getSize", "(Ljavax/accessibility/AccessibleComponent;Ljava/awt/Component;)Ljava/awt/Dimension;", NSZeroSize); - jobject dimension = (*env)->CallStaticObjectMethod(env, jc_Dimension, jm_getSize, axComponent, component); // AWT_THREADING Safe (AWTRunLoopMode) + jobject dimension = (*env)->CallStaticObjectMethod(env, jc_Dimension, jm_getSize, axComponent, component); CHECK_EXCEPTION(); if (dimension == NULL) return NSZeroSize; @@ -71,11 +69,11 @@ NSSize getAxComponentSize(JNIEnv *env, jobject axComponent, jobject component) DECLARE_STATIC_METHOD_RETURN(sjm_getAccessibleRole, sjc_CAccessibility, "getAccessibleRole", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", nil); jobject axRole = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleRole, - axComponent, component); // AWT_THREADING Safe (AWTRunLoopMode) + axComponent, component); CHECK_EXCEPTION(); if (axRole == NULL) return @"unknown"; - NSString* str = JNFJavaToNSString(env, axRole); + NSString* str = JavaStringToNSString(env, axRole); (*env)->DeleteLocalRef(env, axRole); return str; } @@ -86,7 +84,7 @@ jobject getAxSelection(JNIEnv *env, jobject axContext, jobject component) DECLARE_STATIC_METHOD_RETURN(jm_getAccessibleSelection, sjc_CAccessibility, "getAccessibleSelection", "(Ljavax/accessibility/AccessibleContext;Ljava/awt/Component;)Ljavax/accessibility/AccessibleSelection;", nil); jobject o = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getAccessibleSelection, - axContext, component); // AWT_THREADING Safe (AWTRunLoopMode) + axContext, component); CHECK_EXCEPTION(); return o; } @@ -97,7 +95,7 @@ jobject getAxContextSelection(JNIEnv *env, jobject axContext, jint index, jobjec DECLARE_STATIC_METHOD_RETURN(jm_ax_getAccessibleSelection, sjc_CAccessibility, "ax_getAccessibleSelection", "(Ljavax/accessibility/AccessibleContext;ILjava/awt/Component;)Ljavax/accessibility/Accessible;", nil); return (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_ax_getAccessibleSelection, - axContext, index, component); // AWT_THREADING Safe (AWTRunLoopMode) + axContext, index, component); CHECK_EXCEPTION(); } @@ -107,7 +105,7 @@ void setAxContextSelection(JNIEnv *env, jobject axContext, jint index, jobject c DECLARE_STATIC_METHOD(jm_addAccessibleSelection, sjc_CAccessibility, "addAccessibleSelection", "(Ljavax/accessibility/AccessibleContext;ILjava/awt/Component;)V"); (*env)->CallStaticVoidMethod(env, sjc_CAccessibility, jm_addAccessibleSelection, - axContext, index, component); // AWT_THREADING Safe (AWTRunLoopMode) + axContext, index, component); CHECK_EXCEPTION(); } @@ -117,7 +115,7 @@ jobject getAxContext(JNIEnv *env, jobject accessible, jobject component) DECLARE_STATIC_METHOD_RETURN(jm_getAccessibleContext, sjc_CAccessibility, "getAccessibleContext", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleContext;", nil); jobject o = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getAccessibleContext, - accessible, component); // AWT_THREADING Safe (AWTRunLoopMode) + accessible, component); CHECK_EXCEPTION(); return o; } @@ -128,7 +126,7 @@ BOOL isChildSelected(JNIEnv *env, jobject accessible, jint index, jobject compon DECLARE_STATIC_METHOD_RETURN(jm_isAccessibleChildSelected, sjc_CAccessibility, "isAccessibleChildSelected", "(Ljavax/accessibility/Accessible;ILjava/awt/Component;)Z", NO); jboolean b = (*env)->CallStaticBooleanMethod(env, sjc_CAccessibility, jm_isAccessibleChildSelected, - accessible, index, component); // AWT_THREADING Safe (AWTRunLoopMode) + accessible, index, component); CHECK_EXCEPTION(); return b; } @@ -139,7 +137,7 @@ jobject getAxStateSet(JNIEnv *env, jobject axContext, jobject component) DECLARE_STATIC_METHOD_RETURN(jm_getAccessibleStateSet, sjc_CAccessibility, "getAccessibleStateSet", "(Ljavax/accessibility/AccessibleContext;Ljava/awt/Component;)Ljavax/accessibility/AccessibleStateSet;", nil); jobject o = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getAccessibleStateSet, - axContext, component); // AWT_THREADING Safe (AWTRunLoopMode) + axContext, component); CHECK_EXCEPTION(); return o; } @@ -149,7 +147,7 @@ BOOL containsAxState(JNIEnv *env, jobject axContext, jobject axState, jobject co GET_CACCESSIBILITY_CLASS_RETURN(NO); DECLARE_STATIC_METHOD_RETURN(jm_contains, sjc_CAccessibility, "contains", "(Ljavax/accessibility/AccessibleContext;Ljavax/accessibility/AccessibleState;Ljava/awt/Component;)Z", NO); - jboolean b = (*env)->CallStaticBooleanMethod(env, sjc_CAccessibility, jm_contains, axContext, axState, component); // AWT_THREADING Safe (AWTRunLoopMode) + jboolean b = (*env)->CallStaticBooleanMethod(env, sjc_CAccessibility, jm_contains, axContext, axState, component); CHECK_EXCEPTION(); return b; } @@ -210,7 +208,7 @@ NSPoint getAxComponentLocationOnScreen(JNIEnv *env, jobject axComponent, jobject DECLARE_FIELD_RETURN(sjf_X, sjc_Point, "x", "I", NSZeroPoint); DECLARE_FIELD_RETURN(sjf_Y, sjc_Point, "y", "I", NSZeroPoint); jobject jpoint = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getLocationOnScreen, - axComponent, component); // AWT_THREADING Safe (AWTRunLoopMode) + axComponent, component); CHECK_EXCEPTION(); if (jpoint == NULL) return NSZeroPoint; return NSMakePoint((*env)->GetIntField(env, jpoint, sjf_X), (*env)->GetIntField(env, jpoint, sjf_Y)); @@ -221,7 +219,7 @@ jint getAxTextCharCount(JNIEnv *env, jobject axText, jobject component) GET_CACCESSIBILITY_CLASS_RETURN(0); DECLARE_STATIC_METHOD_RETURN(jm_getCharCount, sjc_CAccessibility, "getCharCount", "(Ljavax/accessibility/AccessibleText;Ljava/awt/Component;)I", 0); - int i = (*env)->CallStaticIntMethod(env, sjc_CAccessibility, jm_getCharCount, axText, component); // AWT_THREADING Safe (AWTRunLoopMode) + int i = (*env)->CallStaticIntMethod(env, sjc_CAccessibility, jm_getCharCount, axText, component); CHECK_EXCEPTION(); return i; } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m index 558e1cfccc8..fccd61b91ff 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m @@ -35,7 +35,6 @@ #import -#import #import #import @@ -312,7 +311,7 @@ + (void)initialize NSInteger i; for (i = 0; i < count; i++) { - jstring jString = JNFNSToJavaString(env, [ignoredKeys objectAtIndex:i]); + jstring jString = NSStringToJavaString(env, [ignoredKeys objectAtIndex:i]); (*env)->SetObjectArrayElement(env, result, i, jString); (*env)->DeleteLocalRef(env, jString); } @@ -348,7 +347,7 @@ + (NSArray *)childrenOfParent:(JavaComponentAccessibility *)parent withEnv:(JNIE if (parent->fAccessible == NULL) return nil; GET_CHILDRENANDROLES_METHOD_RETURN(nil); jobjectArray jchildrenAndRoles = (jobjectArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getChildrenAndRoles, - parent->fAccessible, parent->fComponent, whichChildren, allowIgnored); // AWT_THREADING Safe (AWTRunLoop) + parent->fAccessible, parent->fComponent, whichChildren, allowIgnored); CHECK_EXCEPTION(); if (jchildrenAndRoles == NULL) return nil; @@ -368,7 +367,7 @@ + (NSArray *)childrenOfParent:(JavaComponentAccessibility *)parent withEnv:(JNIE DECLARE_FIELD_RETURN(sjf_key, sjc_AccessibleRole, "key", "Ljava/lang/String;", nil); jobject jkey = (*env)->GetObjectField(env, jchildJavaRole, sjf_key); CHECK_EXCEPTION(); - childJavaRole = JNFJavaToNSString(env, jkey); + childJavaRole = JavaStringToNSString(env, jkey); (*env)->DeleteLocalRef(env, jkey); } @@ -490,7 +489,7 @@ - (NSArray *)initializeAttributeNamesWithEnv:(JNIEnv *)env // Get all the other accessibility attributes states we need in one swell foop. // javaRole isn't pulled in because we need protected access to AccessibleRole.key jbooleanArray attributeStates = (jbooleanArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibility, - jm_getInitialAttributeStates, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + jm_getInitialAttributeStates, fAccessible, fComponent); CHECK_EXCEPTION(); if (attributeStates == NULL) return nil; jboolean *attributeStatesArray = (*env)->GetBooleanArrayElements(env, attributeStates, 0); @@ -589,7 +588,7 @@ - (void)getActionsWithEnv:(JNIEnv *)env // On MacOSX, text doesn't have actions, in java it does. // cmcnote: NOT TRUE - Editable text has AXShowMenu. Textfields have AXConfirm. Static text has no actions. - jobject axAction = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getAccessibleAction, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + jobject axAction = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getAccessibleAction, fAccessible, fComponent); CHECK_EXCEPTION(); if (axAction != NULL) { //+++gdb NOTE: In MacOSX, there is just a single Action, not multiple. In java, @@ -866,7 +865,7 @@ - (NSNumber *)accessibilityEnabledAttribute GET_CACCESSIBILITY_CLASS_RETURN(nil); DECLARE_STATIC_METHOD_RETURN(jm_isEnabled, sjc_CAccessibility, "isEnabled", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Z", nil); - NSNumber *value = [NSNumber numberWithBool:(*env)->CallStaticBooleanMethod(env, sjc_CAccessibility, jm_isEnabled, fAccessible, fComponent)]; // AWT_THREADING Safe (AWTRunLoop) + NSNumber *value = [NSNumber numberWithBool:(*env)->CallStaticBooleanMethod(env, sjc_CAccessibility, jm_isEnabled, fAccessible, fComponent)]; CHECK_EXCEPTION(); if (value == nil) { NSLog(@"WARNING: %s called on component that has no accessible component: %@", __FUNCTION__, self); @@ -898,7 +897,7 @@ - (BOOL)accessibilityIsFocusedAttributeSettable // as well as having AccessibleState.FOCUSABLE in its AccessibleStateSet. // We use the former heuristic; if the component focus-traversable, add a focused attribute // See also initializeAttributeNamesWithEnv: - if ((*env)->CallStaticBooleanMethod(env, sjc_CAccessibility, sjm_isFocusTraversable, fAccessible, fComponent)) { // AWT_THREADING Safe (AWTRunLoop) + if ((*env)->CallStaticBooleanMethod(env, sjc_CAccessibility, sjm_isFocusTraversable, fAccessible, fComponent)) { return YES; } CHECK_EXCEPTION(); @@ -915,7 +914,7 @@ - (void)accessibilitySetFocusedAttribute:(id)value if ([(NSNumber*)value boolValue]) { - (*env)->CallStaticVoidMethod(env, sjc_CAccessibility, jm_requestFocus, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + (*env)->CallStaticVoidMethod(env, sjc_CAccessibility, jm_requestFocus, fAccessible, fComponent); CHECK_EXCEPTION(); } } @@ -929,12 +928,12 @@ - (NSString *)accessibilityHelpAttribute DECLARE_STATIC_METHOD_RETURN(sjm_getAccessibleDescription, sjc_CAccessibility, "getAccessibleDescription", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", nil); jobject val = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, - sjm_getAccessibleDescription, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + sjm_getAccessibleDescription, fAccessible, fComponent); CHECK_EXCEPTION(); if (val == NULL) { return nil; } - NSString* str = JNFJavaToNSString(env, val); + NSString* str = JavaStringToNSString(env, val); (*env)->DeleteLocalRef(env, val); return str; } @@ -956,6 +955,32 @@ - (BOOL)accessibilityIsIndexAttributeSettable return NO; } +/* + * The java/lang/Number concrete class could be for any of the Java primitive + * numerical types or some other subclass. + * All existing A11Y code uses Integer so that is what we look for first + * But all must be able to return a double and NSNumber accepts a double, + * so that's the fall back. + */ +static NSNumber* JavaNumberToNSNumber(JNIEnv *env, jobject jnumber) { + if (jnumber == NULL) { + return nil; + } + DECLARE_CLASS_RETURN(jnumber_Class, "java/lang/Number", nil); + DECLARE_CLASS_RETURN(jinteger_Class, "java/lang/Integer", nil); + DECLARE_METHOD_RETURN(jm_intValue, jnumber_Class, "intValue", "()I", nil); + DECLARE_METHOD_RETURN(jm_doubleValue, jnumber_Class, "doubleValue", "()D", nil); + if ((*env)->IsInstanceOf(env, jnumber, jinteger_Class)) { + jint i = (*env)->CallIntMethod(env, jnumber, jm_intValue); + CHECK_EXCEPTION(); + return [NSNumber numberWithInteger:i]; + } else { + jdouble d = (*env)->CallDoubleMethod(env, jnumber, jm_doubleValue); + CHECK_EXCEPTION(); + return [NSNumber numberWithDouble:d]; + } +} + // Element's maximum value (id) - (id)accessibilityMaxValueAttribute { @@ -964,12 +989,12 @@ - (id)accessibilityMaxValueAttribute DECLARE_STATIC_METHOD_RETURN(jm_getMaximumAccessibleValue, sjc_CAccessibility, "getMaximumAccessibleValue", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/Number;", nil); - jobject axValue = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getMaximumAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + jobject axValue = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getMaximumAccessibleValue, fAccessible, fComponent); CHECK_EXCEPTION(); if (axValue == NULL) { return [NSNumber numberWithInt:0]; } - NSNumber* num = JNFJavaToNSNumber(env, axValue); + NSNumber* num = JavaNumberToNSNumber(env, axValue); (*env)->DeleteLocalRef(env, axValue); return num; } @@ -987,12 +1012,12 @@ - (id)accessibilityMinValueAttribute DECLARE_STATIC_METHOD_RETURN(jm_getMinimumAccessibleValue, sjc_CAccessibility, "getMinimumAccessibleValue", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/Number;", nil); - jobject axValue = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getMinimumAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + jobject axValue = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getMinimumAccessibleValue, fAccessible, fComponent); CHECK_EXCEPTION(); if (axValue == NULL) { return [NSNumber numberWithInt:0]; } - NSNumber* num = JNFJavaToNSNumber(env, axValue); + NSNumber* num = JavaNumberToNSNumber(env, axValue); (*env)->DeleteLocalRef(env, axValue); return num; } @@ -1044,7 +1069,7 @@ - (NSValue *)accessibilityPositionAttribute JNIEnv* env = [ThreadUtilities getJNIEnv]; GET_ACCESSIBLECOMPONENT_STATIC_METHOD_RETURN(nil); jobject axComponent = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleComponent, - fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + fAccessible, fComponent); CHECK_EXCEPTION(); // NSAccessibility wants the bottom left point of the object in @@ -1115,7 +1140,7 @@ - (NSString *)accessibilityRoleDescriptionAttribute jobject axRole = (*env)->CallStaticObjectMethod(env, jm_getAccessibleRoleDisplayString, fAccessible, fComponent); CHECK_EXCEPTION(); if (axRole != NULL) { - value = JNFJavaToNSString(env, axRole); + value = JavaStringToNSString(env, axRole); (*env)->DeleteLocalRef(env, axRole); } else { value = @"unknown"; @@ -1171,7 +1196,7 @@ - (void)accessibilitySetSelectedAttribute:(id)value "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)V"); if ([(NSNumber*)value boolValue]) { - (*env)->CallStaticVoidMethod(env, sjc_CAccessibility, jm_requestSelection, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + (*env)->CallStaticVoidMethod(env, sjc_CAccessibility, jm_requestSelection, fAccessible, fComponent); CHECK_EXCEPTION(); } } @@ -1181,7 +1206,7 @@ - (NSValue *)accessibilitySizeAttribute { JNIEnv* env = [ThreadUtilities getJNIEnv]; GET_ACCESSIBLECOMPONENT_STATIC_METHOD_RETURN(nil); jobject axComponent = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, - sjm_getAccessibleComponent, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + sjm_getAccessibleComponent, fAccessible, fComponent); CHECK_EXCEPTION(); NSValue* size = [NSValue valueWithSize:getAxComponentSize(env, axComponent, fComponent)]; (*env)->DeleteLocalRef(env, axComponent); @@ -1243,12 +1268,12 @@ - (NSString *)accessibilityTitleAttribute JNIEnv* env = [ThreadUtilities getJNIEnv]; GET_ACCESSIBLENAME_METHOD_RETURN(nil); - jobject val = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleName, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + jobject val = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleName, fAccessible, fComponent); CHECK_EXCEPTION(); if (val == NULL) { return nil; } - NSString* str = JNFJavaToNSString(env, val); + NSString* str = JavaStringToNSString(env, val); (*env)->DeleteLocalRef(env, val); return str; } @@ -1304,12 +1329,12 @@ - (id)accessibilityValueAttribute (*env)->CallStaticObjectMethod( env, sjm_getAccessibleName, selectedMenuItem->fAccessible, - selectedMenuItem->fComponent ); // AWT_THREADING Safe (AWTRunLoop) + selectedMenuItem->fComponent ); CHECK_EXCEPTION(); if (itemValue == NULL) { return nil; } - NSString* itemString = JNFJavaToNSString(env, itemValue); + NSString* itemString = JavaStringToNSString(env, itemValue); (*env)->DeleteLocalRef(env, itemValue); return itemString; } else { @@ -1326,7 +1351,7 @@ - (id)accessibilityValueAttribute GET_CACCESSIBILITY_CLASS_RETURN(nil); DECLARE_STATIC_METHOD_RETURN(sjm_getAccessibleValue, sjc_CAccessibility, "getAccessibleValue", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljavax/accessibility/AccessibleValue;", nil); - jobject axValue = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleValue, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + jobject axValue = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getAccessibleValue, fAccessible, fComponent); CHECK_EXCEPTION(); if (axValue != NULL) { DECLARE_STATIC_METHOD_RETURN(jm_getCurrentAccessibleValue, sjc_CAccessibility, "getCurrentAccessibleValue", @@ -1334,7 +1359,7 @@ - (id)accessibilityValueAttribute jobject str = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getCurrentAccessibleValue, axValue, fComponent); CHECK_EXCEPTION(); if (str != NULL) { - num = JNFJavaToNSNumber(env, str); // AWT_THREADING Safe (AWTRunLoop) + num = JavaNumberToNSNumber(env, str); (*env)->DeleteLocalRef(env, str); } (*env)->DeleteLocalRef(env, axValue); @@ -1442,7 +1467,7 @@ - (id)accessibilityHitTest:(NSPoint)point withEnv:(JNIEnv *)env id value = nil; if ((*env)->IsInstanceOf(env, jparent, jc_Container)) { jobject jaccessible = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_accessibilityHitTest, - jparent, (jfloat)point.x, (jfloat)point.y); // AWT_THREADING Safe (AWTRunLoop) + jparent, (jfloat)point.x, (jfloat)point.y); CHECK_EXCEPTION(); if (jaccessible != NULL) { value = [JavaComponentAccessibility createWithAccessible:jaccessible withEnv:env withView:fView]; @@ -1472,7 +1497,7 @@ - (id)accessibilityFocusedUIElement id value = nil; NSWindow* hostWindow = [[self->fView window] retain]; - jobject focused = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop) + jobject focused = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getFocusOwner, fComponent); [hostWindow release]; CHECK_EXCEPTION(); @@ -1674,7 +1699,7 @@ - (NSArray *)tabControlsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axC { GET_CHILDRENANDROLES_METHOD_RETURN(nil); jobjectArray jtabsAndRoles = (jobjectArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibility, jm_getChildrenAndRoles, - fAccessible, fComponent, whichTabs, allowIgnored); // AWT_THREADING Safe (AWTRunLoop) + fAccessible, fComponent, whichTabs, allowIgnored); CHECK_EXCEPTION(); if(jtabsAndRoles == NULL) return nil; @@ -1695,7 +1720,7 @@ - (NSArray *)tabControlsWithEnv:(JNIEnv *)env withTabGroupAxContext:(jobject)axC DECLARE_FIELD_RETURN(sjf_key, sjc_AccessibleRole, "key", "Ljava/lang/String;", nil); jobject jkey = (*env)->GetObjectField(env, jtabJavaRole, sjf_key); CHECK_EXCEPTION(); - NSString *tabJavaRole = JNFJavaToNSString(env, jkey); + NSString *tabJavaRole = JavaStringToNSString(env, jkey); (*env)->DeleteLocalRef(env, jkey); NSInteger i; @@ -2050,11 +2075,11 @@ static BOOL ObjectEquals(JNIEnv *env, jobject a, jobject b, jobject component) DECLARE_CLASS_RETURN(sjc_LWCToolkit, "sun/lwawt/macosx/LWCToolkit", NO); DECLARE_STATIC_METHOD_RETURN(jm_doEquals, sjc_LWCToolkit, "doEquals", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/awt/Component;)Z", NO); - return (*env)->CallStaticBooleanMethod(env, sjc_LWCToolkit, jm_doEquals, a, b, component); // AWT_THREADING Safe (AWTRunLoopMode) + return (*env)->CallStaticBooleanMethod(env, sjc_LWCToolkit, jm_doEquals, a, b, component); CHECK_EXCEPTION(); } - jboolean jb = (*env)->CallBooleanMethod(env, a, jm_equals, b); // AWT_THREADING Safe (!appKit) + jboolean jb = (*env)->CallBooleanMethod(env, a, jm_equals, b); CHECK_EXCEPTION(); return jb; } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m index d662aaef5f7..730e98e4147 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaTextAccessibility.m @@ -134,10 +134,10 @@ - (NSString *)accessibilityValueAttribute if ([[self accessibilityRoleAttribute] isEqualToString:NSAccessibilityStaticTextRole]) { // if it's static text, the AppKit AXValue is the java accessibleName jobject axName = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, - sjm_getAccessibleName, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + sjm_getAccessibleName, fAccessible, fComponent); CHECK_EXCEPTION(); if (axName != NULL) { - NSString* str = JNFJavaToNSString(env, axName); + NSString* str = JavaStringToNSString(env, axName); (*env)->DeleteLocalRef(env, axName); return str; } @@ -147,14 +147,14 @@ - (NSString *)accessibilityValueAttribute // cmcnote: inefficient to make three distinct JNI calls. Coalesce. radr://3951923 GET_ACCESSIBLETEXT_METHOD_RETURN(@""); jobject axText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, - sjm_getAccessibleText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + sjm_getAccessibleText, fAccessible, fComponent); CHECK_EXCEPTION(); if (axText == NULL) return nil; (*env)->DeleteLocalRef(env, axText); GET_ACCESSIBLEEDITABLETEXT_METHOD_RETURN(nil); jobject axEditableText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, - sjm_getAccessibleEditableText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + sjm_getAccessibleEditableText, fAccessible, fComponent); CHECK_EXCEPTION(); if (axEditableText == NULL) return nil; @@ -163,7 +163,7 @@ - (NSString *)accessibilityValueAttribute jobject jrange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getTextRange, axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent); CHECK_EXCEPTION(); - NSString *string = JNFJavaToNSString(env, jrange); // AWT_THREADING Safe (AWTRunLoop) + NSString *string = JavaStringToNSString(env, jrange); (*env)->DeleteLocalRef(env, jrange); (*env)->DeleteLocalRef(env, axEditableText); @@ -181,7 +181,7 @@ - (BOOL)accessibilityIsValueAttributeSettable JNIEnv* env = [ThreadUtilities getJNIEnv]; GET_ACCESSIBLEEDITABLETEXT_METHOD_RETURN(NO); jobject axEditableText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, - sjm_getAccessibleEditableText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + sjm_getAccessibleEditableText, fAccessible, fComponent); CHECK_EXCEPTION(); if (axEditableText == NULL) return NO; (*env)->DeleteLocalRef(env, axEditableText); @@ -204,10 +204,10 @@ - (NSString *)accessibilitySelectedTextAttribute DECLARE_STATIC_METHOD_RETURN(jm_getSelectedText, sjc_CAccessibleText, "getSelectedText", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)Ljava/lang/String;", nil); jobject axText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getSelectedText, - fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + fAccessible, fComponent); CHECK_EXCEPTION(); if (axText == NULL) return @""; - NSString* str = JNFJavaToNSString(env, axText); + NSString* str = JavaStringToNSString(env, axText); (*env)->DeleteLocalRef(env, axText); return str; } @@ -227,12 +227,12 @@ - (void)accessibilitySetSelectedTextAttribute:(id)value #endif JNIEnv *env = [ThreadUtilities getJNIEnv]; - jstring jstringValue = JNFNSToJavaString(env, (NSString *)value); + jstring jstringValue = NSStringToJavaString(env, (NSString *)value); GET_CACCESSIBLETEXT_CLASS(); DECLARE_STATIC_METHOD(jm_setSelectedText, sjc_CAccessibleText, "setSelectedText", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;Ljava/lang/String;)V"); (*env)->CallStaticVoidMethod(env, sjc_CAccessibleText, jm_setSelectedText, - fAccessible, fComponent, jstringValue); // AWT_THREADING Safe (AWTRunLoop) + fAccessible, fComponent, jstringValue); CHECK_EXCEPTION(); } @@ -244,7 +244,7 @@ - (NSValue *)accessibilitySelectedTextRangeAttribute DECLARE_STATIC_METHOD_RETURN(jm_getSelectedTextRange, sjc_CAccessibleText, "getSelectedTextRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[I", nil); jintArray axTextRange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, - jm_getSelectedTextRange, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + jm_getSelectedTextRange, fAccessible, fComponent); CHECK_EXCEPTION(); if (axTextRange == NULL) return nil; @@ -274,7 +274,7 @@ - (void)accessibilitySetSelectedTextRangeAttribute:(id)value DECLARE_STATIC_METHOD(jm_setSelectedTextRange, sjc_CAccessibleText, "setSelectedTextRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)V"); (*env)->CallStaticVoidMethod(env, sjc_CAccessibleText, jm_setSelectedTextRange, - fAccessible, fComponent, startIndex, endIndex); // AWT_THREADING Safe (AWTRunLoop) + fAccessible, fComponent, startIndex, endIndex); CHECK_EXCEPTION(); } @@ -285,7 +285,7 @@ - (NSNumber *)accessibilityNumberOfCharactersAttribute JNIEnv *env = [ThreadUtilities getJNIEnv]; GET_ACCESSIBLETEXT_METHOD_RETURN(nil); jobject axText = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, - sjm_getAccessibleText, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + sjm_getAccessibleText, fAccessible, fComponent); CHECK_EXCEPTION(); NSNumber* num = [NSNumber numberWithInt:getAxTextCharCount(env, axText, fComponent)]; (*env)->DeleteLocalRef(env, axText); @@ -304,7 +304,7 @@ - (NSValue *)accessibilityVisibleCharacterRangeAttribute DECLARE_STATIC_METHOD_RETURN(jm_getVisibleCharacterRange, sjc_CAccessibleText, "getVisibleCharacterRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[I", nil); jintArray axTextRange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, - jm_getVisibleCharacterRange, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + jm_getVisibleCharacterRange, fAccessible, fComponent); CHECK_EXCEPTION(); if (axTextRange == NULL) return nil; @@ -326,7 +326,7 @@ - (NSValue *)accessibilityInsertionPointLineNumberAttribute DECLARE_STATIC_METHOD_RETURN(jm_getLineNumberForInsertionPoint, sjc_CAccessibleText, "getLineNumberForInsertionPoint", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)I", nil); jint row = (*env)->CallStaticIntMethod(env, sjc_CAccessibleText, - jm_getLineNumberForInsertionPoint, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + jm_getLineNumberForInsertionPoint, fAccessible, fComponent); CHECK_EXCEPTION(); if (row < 0) return nil; return [NSNumber numberWithInt:row]; @@ -365,7 +365,7 @@ - (NSValue *)accessibilityBoundsForRangeAttributeForParameter:(id)parameter DECLARE_STATIC_METHOD_RETURN(jm_getBoundsForRange, sjc_CAccessibleText, "getBoundsForRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)[D", nil); jdoubleArray axBounds = (jdoubleArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getBoundsForRange, - fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop) + fAccessible, fComponent, range.location, range.length); CHECK_EXCEPTION(); if (axBounds == NULL) return nil; @@ -397,7 +397,7 @@ - (NSNumber *)accessibilityLineForIndexAttributeForParameter:(id)parameter DECLARE_STATIC_METHOD_RETURN(jm_getLineNumberForIndex, sjc_CAccessibleText, "getLineNumberForIndex", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)I", nil); jint row = (*env)->CallStaticIntMethod(env, sjc_CAccessibleText, jm_getLineNumberForIndex, - fAccessible, fComponent, [line intValue]); // AWT_THREADING Safe (AWTRunLoop) + fAccessible, fComponent, [line intValue]); CHECK_EXCEPTION(); if (row < 0) return nil; return [NSNumber numberWithInt:row]; @@ -413,7 +413,7 @@ - (NSValue *)accessibilityRangeForLineAttributeForParameter:(id)parameter DECLARE_STATIC_METHOD_RETURN(jm_getRangeForLine, sjc_CAccessibleText, "getRangeForLine", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I", nil); jintArray axTextRange = (jintArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, - jm_getRangeForLine, fAccessible, fComponent, [line intValue]); // AWT_THREADING Safe (AWTRunLoop) + jm_getRangeForLine, fAccessible, fComponent, [line intValue]); CHECK_EXCEPTION(); if (axTextRange == NULL) return nil; @@ -443,10 +443,10 @@ - (NSString *)accessibilityStringForRangeAttributeForParameter:(id)parameter DECLARE_STATIC_METHOD_RETURN(jm_getStringForRange, sjc_CAccessibleText, "getStringForRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)Ljava/lang/String;", nil); jstring jstringForRange = (jstring)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getStringForRange, - fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop) + fAccessible, fComponent, range.location, range.length); CHECK_EXCEPTION(); if (jstringForRange == NULL) return @""; - NSString* str = JNFJavaToNSString(env, jstringForRange); + NSString* str = JavaStringToNSString(env, jstringForRange); (*env)->DeleteLocalRef(env, jstringForRange); return str; } @@ -475,7 +475,7 @@ - (NSValue *)accessibilityRangeForPositionAttributeForParameter:(id)parameter DECLARE_STATIC_METHOD_RETURN(jm_getCharacterIndexAtPosition, sjc_CAccessibleText, "getCharacterIndexAtPosition", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)I", nil); jint charIndex = (*env)->CallStaticIntMethod(env, sjc_CAccessibleText, jm_getCharacterIndexAtPosition, - fAccessible, fComponent, point.x, point.y); // AWT_THREADING Safe (AWTRunLoop) + fAccessible, fComponent, point.x, point.y); CHECK_EXCEPTION(); if (charIndex == -1) return nil; @@ -508,7 +508,7 @@ - (NSValue *)accessibilityRangeForIndexAttributeForParameter:(id)parameter DECLARE_STATIC_METHOD_RETURN(jm_getRangeForIndex, sjc_CAccessibleText, "getRangeForIndex", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)[I", nil); jintArray axTextRange = (jintArray)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getRangeForIndex, - fAccessible, fComponent, index); // AWT_THREADING Safe (AWTRunLoop) + fAccessible, fComponent, index); CHECK_EXCEPTION(); if (axTextRange == NULL) return nil; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m index 982935ce69e..1c3fd329c59 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m @@ -456,7 +456,7 @@ + (void)starter:(BOOL)wasOnMainThread headless:(BOOL)headless { // could happen if we are embedded inside SWT application, // in this case just spin a single empty block through // the event loop to give it a chance to process pending events - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){}]; + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){}]; } if (([AWTToolkit getEventCount] - currentEventNum) != 0) { @@ -517,7 +517,7 @@ BOOL doLoadNativeColors(JNIEnv *env, jintArray jColors, BOOL useAppleColors) { UInt32 colorsArray[len]; UInt32 *colors = colorsArray; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ NSUInteger i; for (i = 0; i < len; i++) { colors[i] = RGB([CSystemColors getColor:i useAppleColor:useAppleColors]); @@ -587,7 +587,7 @@ BOOL doLoadNativeColors(JNIEnv *env, jintArray jColors, BOOL useAppleColors) { // Don't use acceptInputForMode because that doesn't setup autorelease pools properly BOOL isRunning = true; while (![mediatorObject shouldEndRunLoop] && isRunning) { - isRunning = [[NSRunLoop currentRunLoop] runMode:(inAWT ? [JNFRunLoop javaRunLoopMode] : NSDefaultRunLoopMode) + isRunning = [[NSRunLoop currentRunLoop] runMode:(inAWT ? [ThreadUtilities javaRunLoopMode] : NSDefaultRunLoopMode) beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.010]]; if (processEvents) { //We do not spin a runloop here as date is nil, so does not matter which mode to use @@ -654,7 +654,7 @@ BOOL doLoadNativeColors(JNIEnv *env, jintArray jColors, BOOL useAppleColors) { (JNIEnv *env, jobject self) { __block jboolean isOn = JNI_FALSE; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ NSUInteger modifiers = [NSEvent modifierFlags]; isOn = (modifiers & NSAlphaShiftKeyMask) != 0; }]; @@ -727,7 +727,7 @@ BOOL doLoadNativeColors(JNIEnv *env, jintArray jColors, BOOL useAppleColors) { Java_sun_font_FontManager_getFontPath (JNIEnv *env, jclass obj, jboolean noType1) { - return JNFNSToJavaString(env, @"/Library/Fonts"); + return NSStringToJavaString(env, @"/Library/Fonts"); } // This isn't yet used on unix, the implementation is added since shared @@ -869,7 +869,7 @@ JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { Java_sun_lwawt_macosx_LWCToolkit_getMultiClickTime(JNIEnv *env, jclass klass) { __block jint multiClickTime = 0; JNI_COCOA_ENTER(env); - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ multiClickTime = (jint)([NSEvent doubleClickInterval] * 1000); }]; JNI_COCOA_EXIT(env); diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/PrintModel.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/PrintModel.m index 84e03dc7d6e..d25fbd8cae5 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/PrintModel.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/PrintModel.m @@ -26,8 +26,6 @@ #import "PrintModel.h" -#import - #import "PrinterView.h" #import "ThreadUtilities.h" #import "JNIUtilities.h" @@ -53,7 +51,7 @@ - (void)dealloc { - (BOOL)runPageSetup { __block BOOL fResult = NO; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ NSPageLayout* pageLayout = [NSPageLayout pageLayout]; fResult = ([pageLayout runModalWithPrintInfo:fPrintInfo] == NSOKButton); }]; @@ -64,7 +62,7 @@ - (BOOL)runPageSetup { - (BOOL)runJobSetup { __block BOOL fResult = NO; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ NSPrintPanel* printPanel = [NSPrintPanel printPanel]; fResult = ([printPanel runModalWithPrintInfo:fPrintInfo] == NSOKButton); }]; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/PrinterSurfaceData.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/PrinterSurfaceData.m index 5a2916a38f2..8bcda8d485b 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/PrinterSurfaceData.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/PrinterSurfaceData.m @@ -26,8 +26,6 @@ #import "PrinterSurfaceData.h" #import "jni_util.h" -#import - //#define DEBUG 1 #if defined DEBUG diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/PrinterView.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/PrinterView.m index a64fba4eac3..17feca9fd7e 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/PrinterView.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/PrinterView.m @@ -28,8 +28,6 @@ #import "java_awt_print_Pageable.h" #import "java_awt_print_PageFormat.h" -#import - #import "ThreadUtilities.h" #import "GeomUtilities.h" #import "JNIUtilities.h" @@ -106,7 +104,7 @@ - (void)drawRect:(NSRect)aRect CGContextSaveGState(cgRef); //04/28/2004: state needs to be saved here due to addition of lazy state management (*env)->CallVoidMethod(env, fPrinterJob, jm_printToPathGraphics, fCurPeekGraphics, fPrinterJob, - fCurPainter, fCurPageFormat, jPageIndex, context); // AWT_THREADING Safe (AWTRunLoop) + fCurPainter, fCurPageFormat, jPageIndex, context); CHECK_EXCEPTION(); CGContextRestoreGState(cgRef); @@ -122,9 +120,9 @@ - (NSString*)printJobTitle GET_CPRINTERJOB_CLASS_RETURN(nil); DECLARE_METHOD_RETURN(jm_getJobName, sjc_CPrinterJob, "getJobName", "()Ljava/lang/String;", nil); - jobject o = (*env)->CallObjectMethod(env, fPrinterJob, jm_getJobName); // AWT_THREADING Safe (known object) + jobject o = (*env)->CallObjectMethod(env, fPrinterJob, jm_getJobName); CHECK_EXCEPTION(); - id result = JNFJavaToNSString(env, o); + id result = JavaStringToNSString(env, o); (*env)->DeleteLocalRef(env, o); return result; } @@ -195,7 +193,7 @@ - (NSRect)rectForPage:(NSInteger)pageNumber } jobjectArray objectArray = (*env)->CallObjectMethod(env, fPrinterJob, - jm_getPageformatPrintablePeekgraphics, jPageNumber); // AWT_THREADING Safe (AWTRunLoopMode) + jm_getPageformatPrintablePeekgraphics, jPageNumber); CHECK_EXCEPTION(); if (objectArray != NULL) { // Get references to the return objects -> PageFormat, Printable, PeekGraphics @@ -214,7 +212,7 @@ - (NSRect)rectForPage:(NSInteger)pageNumber // Actually print and get the PageFormatArea jobject pageFormatArea = (*env)->CallObjectMethod(env, fPrinterJob, jm_printAndGetPageFormatArea, fCurPainter, - fCurPeekGraphics, fCurPageFormat, jPageNumber); // AWT_THREADING Safe (AWTRunLoopMode) + fCurPeekGraphics, fCurPageFormat, jPageNumber); CHECK_EXCEPTION(); if (pageFormatArea != NULL) { NSPrintingOrientation currentOrientation = diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzRenderer.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzRenderer.m index 242caf9c4e2..f97a7384fc7 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzRenderer.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzRenderer.m @@ -28,7 +28,6 @@ #import "sun_java2d_OSXSurfaceData.h" #import -#import #import "ImageSurfaceData.h" diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.m index b8299a9053b..b53863bad2d 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.m @@ -35,8 +35,6 @@ #import "sun_lwawt_macosx_CPrinterSurfaceData.h" #import "ImageSurfaceData.h" -#import - #import #import "ThreadUtilities.h" diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m index 3b87018c12a..93f843eb975 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonComponentAccessibility.m @@ -46,7 +46,7 @@ + (void) initializeRolesMap { /* * Here we should keep all the mapping between the accessibility roles and implementing classes */ - rolesMap = [[NSMutableDictionary alloc] initWithCapacity:6]; + rolesMap = [[NSMutableDictionary alloc] initWithCapacity:7]; [rolesMap setObject:@"ButtonAccessibility" forKey:@"pushbutton"]; [rolesMap setObject:@"ImageAccessibility" forKey:@"icon"]; @@ -54,6 +54,7 @@ + (void) initializeRolesMap { [rolesMap setObject:@"SpinboxAccessibility" forKey:@"spinbox"]; [rolesMap setObject:@"StaticTextAccessibility" forKey:@"hyperlink"]; [rolesMap setObject:@"StaticTextAccessibility" forKey:@"label"]; + [rolesMap setObject:@"RadiobuttonAccessibility" forKey:@"radiobutton"]; } /* diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonTextAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonTextAccessibility.m index 69791fd569d..007cbe9de8c 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonTextAccessibility.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/CommonTextAccessibility.m @@ -75,7 +75,7 @@ - (nullable NSString *)accessibilityValueAttribute sjm_getAccessibleName, fAccessible, fComponent); CHECK_EXCEPTION(); if (axName != NULL) { - NSString* str = JNFJavaToNSString(env, axName); + NSString* str = JavaStringToNSString(env, axName); (*env)->DeleteLocalRef(env, axName); return str; } @@ -100,7 +100,7 @@ - (nullable NSString *)accessibilityValueAttribute jobject jrange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getTextRange, axEditableText, 0, getAxTextCharCount(env, axEditableText, fComponent), fComponent); CHECK_EXCEPTION(); - NSString *string = JNFJavaToNSString(env, jrange); // AWT_THREADING Safe (AWTRunLoop) + NSString *string = JavaStringToNSString(env, jrange); (*env)->DeleteLocalRef(env, jrange); (*env)->DeleteLocalRef(env, axEditableText); @@ -116,7 +116,7 @@ - (NSRange)accessibilityVisibleCharacterRangeAttribute DECLARE_STATIC_METHOD_RETURN(jm_getVisibleCharacterRange, sjc_CAccessibleText, "getVisibleCharacterRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;)[I", DEFAULT_RANGE); jintArray axTextRange = (*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, - jm_getVisibleCharacterRange, fAccessible, fComponent); // AWT_THREADING Safe (AWTRunLoop) + jm_getVisibleCharacterRange, fAccessible, fComponent); CHECK_EXCEPTION(); if (axTextRange == NULL) return DEFAULT_RANGE; @@ -130,10 +130,10 @@ - (nullable NSString *)accessibilityStringForRangeAttribute:(NSRange)range DECLARE_STATIC_METHOD_RETURN(jm_getStringForRange, sjc_CAccessibleText, "getStringForRange", "(Ljavax/accessibility/Accessible;Ljava/awt/Component;II)Ljava/lang/String;", nil); jstring jstringForRange = (jstring)(*env)->CallStaticObjectMethod(env, sjc_CAccessibleText, jm_getStringForRange, - fAccessible, fComponent, range.location, range.length); // AWT_THREADING Safe (AWTRunLoop) + fAccessible, fComponent, range.location, range.length); CHECK_EXCEPTION(); if (jstringForRange == NULL) return @""; - NSString* str = JNFJavaToNSString(env, jstringForRange); + NSString* str = JavaStringToNSString(env, jstringForRange); (*env)->DeleteLocalRef(env, jstringForRange); return str; } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/RadiobuttonAccessibility.h b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/RadiobuttonAccessibility.h new file mode 100644 index 00000000000..e384eefe64c --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/RadiobuttonAccessibility.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#import "ButtonAccessibility.h" + +#import + +@interface RadiobuttonAccessibility : ButtonAccessibility { + +}; +- (id)accessibilityValue; +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/RadiobuttonAccessibility.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/RadiobuttonAccessibility.m new file mode 100644 index 00000000000..f596d080b88 --- /dev/null +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/a11y/RadiobuttonAccessibility.m @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#import "RadiobuttonAccessibility.h" +#import "JNIUtilities.h" +#import "ThreadUtilities.h" + +/* + * Implementation of the accessibility peer for the pushbutton role + */ +@implementation RadiobuttonAccessibility + +- (id) accessibilityValue +{ + AWT_ASSERT_APPKIT_THREAD; + return [self accessibilityValueAttribute]; +} + +@end diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m index 2772c91a89c..0f27514b910 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m @@ -23,8 +23,6 @@ * questions. */ -#import - #import "java_awt_Font.h" #import "sun_awt_PlatformFont.h" #import "sun_awt_FontDescriptor.h" @@ -310,9 +308,9 @@ static OSStatus CreateFSRef(FSRef *myFSRefPtr, NSString *inPath) jint i; for (i = 0; i < num; i++) { NSString *fontname = [filteredFonts objectAtIndex:i]; - jobject jFontName = JNFNSToJavaString(env, fontname); + jobject jFontName = NSStringToJavaString(env, fontname); jobject jFontFamilyName = - JNFNSToJavaString(env, GetFamilyNameForFontName(fontname)); + NSStringToJavaString(env, GetFamilyNameForFontName(fontname)); (*env)->CallVoidMethod(env, jthis, jm_registerFont, jFontName, jFontFamilyName); CHECK_EXCEPTION(); @@ -334,7 +332,7 @@ static OSStatus CreateFSRef(FSRef *myFSRefPtr, NSString *inPath) { JNI_COCOA_ENTER(env); - NSString *path = JNFJavaToNSString(env, filename); + NSString *path = JavaStringToNSString(env, filename); NSURL *url = [NSURL fileURLWithPath:(NSString *)path]; bool res = CTFontManagerRegisterFontsForURL((CFURLRef)url, kCTFontManagerScopeProcess, nil); #ifdef DEBUG @@ -434,7 +432,7 @@ static OSStatus CreateFSRef(FSRef *myFSRefPtr, NSString *inPath) JNI_COCOA_ENTER(env); awtFont = - [AWTFont awtFontForName:JNFJavaToNSString(env, nativeFontName) + [AWTFont awtFontForName:JavaStringToNSString(env, nativeFontName) style:style]; // autoreleased if (awtFont) { @@ -546,6 +544,7 @@ static OSStatus CreateFSRef(FSRef *myFSRefPtr, NSString *inPath) Java_sun_font_CFont_getCascadeList (JNIEnv *env, jclass cls, jlong awtFontPtr, jobject arrayListOfString) { +JNI_COCOA_ENTER(env); jclass alc = (*env)->FindClass(env, "java/util/ArrayList"); if (alc == NULL) return; jmethodID addMID = (*env)->GetMethodID(env, alc, "add", "(Ljava/lang/Object;)Z"); @@ -555,13 +554,15 @@ static OSStatus CreateFSRef(FSRef *myFSRefPtr, NSString *inPath) AWTFont *awtFont = (AWTFont *)jlong_to_ptr(awtFontPtr); NSFont* nsFont = awtFont->fFont; CTFontRef font = (CTFontRef)nsFont; - CFStringRef base = CTFontCopyFullName(font); CFArrayRef codes = CFLocaleCopyISOLanguageCodes(); #ifdef DEBUG + CFStringRef base = CTFontCopyFullName(font); NSLog(@"BaseFont is : %@", (NSString*)base); + CFRelease(base); #endif CFArrayRef fds = CTFontCopyDefaultCascadeListForLanguages(font, codes); + CFRelease(codes); CFIndex cnt = CFArrayGetCount(fds); for (i=0; iCallBooleanMethod(env, arrayListOfString, addMID, jFontName); if ((*env)->ExceptionOccurred(env)) { + CFRelease(fds); return; } (*env)->DeleteLocalRef(env, jFontName); } + CFRelease(fds); +JNI_COCOA_EXIT(env); } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m index 5b1ec30936d..2c991a2fc2f 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/AWTStrike.m @@ -23,7 +23,6 @@ * questions. */ -#import #import "java_awt_geom_PathIterator.h" #import "sun_font_CStrike.h" #import "sun_font_CStrikeDisposer.h" diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/CCharToGlyphMapper.m b/src/java.desktop/macosx/native/libawt_lwawt/font/CCharToGlyphMapper.m index a2a150c2be5..393d33bdbe6 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/CCharToGlyphMapper.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/CCharToGlyphMapper.m @@ -25,8 +25,6 @@ #import "JNIUtilities.h" -#import - #import "AWTFont.h" #import "CoreTextSupport.h" diff --git a/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m b/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m index d6940ed6f72..d8deec3b283 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/font/CGGlyphImages.m @@ -24,8 +24,8 @@ */ #import // for vImage_Buffer -#import +#import "JNIUtilities.h" #import "CGGlyphImages.h" #import "CoreTextSupport.h" #import "fontscalerdefs.h" // contains the definition of GlyphInfo struct diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m index 507290c0895..ca8717bc819 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m @@ -33,7 +33,6 @@ #import #import #import -#import /** * Disposes all memory and resources associated with the given @@ -123,6 +122,7 @@ __block jlong ret = 0L; JNI_COCOA_ENTER(env); [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ + JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; J2dRlsTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_getCGLConfigInfo"); @@ -288,6 +288,7 @@ [NSOpenGLContext clearCurrentContext]; ret = ptr_to_jlong(cglinfo); [pool drain]; + }]; JNI_COCOA_EXIT(env); return ret; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.h b/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.h index b5428a7ff1f..b4fc62fbbaa 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLLayer.h @@ -26,8 +26,6 @@ #ifndef CGLLayer_h_Included #define CGLLayer_h_Included -#import - @interface CGLLayer : CAOpenGLLayer { @private diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m index fe4ffc4504d..b90d4ff00ea 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m @@ -315,7 +315,7 @@ extern CGLError CGLTexImageIOSurface2D( CGLSDOps *dstCGLOps = (CGLSDOps *)dstOps->privOps; CGLLayer *layer = (CGLLayer*)dstCGLOps->layer; if (layer != NULL) { - [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ AWT_ASSERT_APPKIT_THREAD; [layer setNeedsDisplay]; }]; diff --git a/src/java.desktop/macosx/native/libosx/CFileManager.m b/src/java.desktop/macosx/native/libosx/CFileManager.m index e89847966cf..9106e824132 100644 --- a/src/java.desktop/macosx/native/libosx/CFileManager.m +++ b/src/java.desktop/macosx/native/libosx/CFileManager.m @@ -26,12 +26,9 @@ #import "com_apple_eio_FileManager.h" #import "JNIUtilities.h" - -#import -#import - #import "ThreadUtilities.h" +#import /* * Class: com_apple_eio_FileManager @@ -42,7 +39,7 @@ (JNIEnv *env, jclass clz, jstring javaFilename, jint type, jint creator) { JNI_COCOA_ENTER(env); - NSString *filename = JNFNormalizedNSStringForPath(env, javaFilename); + NSString *filename = NormalizedPathNSStringFromJavaString(env, javaFilename); NSDictionary *attr = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:type], NSFileHFSTypeCode, [NSNumber numberWithInt:creator], NSFileHFSCreatorCode, nil]; @@ -59,7 +56,7 @@ (JNIEnv *env, jclass ckz, jstring javaFilename, jint type) { JNI_COCOA_ENTER(env); - NSString *filename = JNFNormalizedNSStringForPath(env, javaFilename); + NSString *filename = NormalizedPathNSStringFromJavaString(env, javaFilename); NSDictionary *attr = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:type] forKey:NSFileHFSTypeCode]; [[NSFileManager defaultManager] changeFileAttributes:attr atPath:filename]; JNI_COCOA_EXIT(env); @@ -74,7 +71,7 @@ (JNIEnv *env, jclass clz, jstring javaFilename, jint creator) { JNI_COCOA_ENTER(env); - NSString *filename = JNFNormalizedNSStringForPath(env, javaFilename); + NSString *filename = NormalizedPathNSStringFromJavaString(env, javaFilename); NSDictionary *attr = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:creator] forKey:NSFileHFSCreatorCode]; [[NSFileManager defaultManager] changeFileAttributes:attr atPath:filename]; JNI_COCOA_EXIT(env); @@ -90,7 +87,7 @@ { jint type = 0; JNI_COCOA_ENTER(env); - NSString *filename = JNFNormalizedNSStringForPath(env, javaFilename); + NSString *filename = NormalizedPathNSStringFromJavaString(env, javaFilename); NSDictionary *attributes = [[NSFileManager defaultManager] fileAttributesAtPath:filename traverseLink:YES]; NSNumber *val = [attributes objectForKey:NSFileHFSTypeCode]; type = [val intValue]; @@ -108,7 +105,7 @@ { jint creator = 0; JNI_COCOA_ENTER(env); - NSString *filename = JNFNormalizedNSStringForPath(env, javaFilename); + NSString *filename = NormalizedPathNSStringFromJavaString(env, javaFilename); NSDictionary *attributes = [[NSFileManager defaultManager] fileAttributesAtPath:filename traverseLink:YES]; NSNumber *val = [attributes objectForKey:NSFileHFSCreatorCode]; creator = [val intValue]; @@ -133,7 +130,7 @@ char path[PATH_MAX]; if (FSRefMakePath(&foundRef, (UInt8 *)path, sizeof(path)) == noErr) { NSString *filenameString = [[NSFileManager defaultManager] stringWithFileSystemRepresentation:path length:strlen(path)]; - filename = JNFNormalizedJavaStringForPath(env, filenameString); + filename = NormalizedPathJavaStringFromNSString(env, filenameString); } } @@ -152,10 +149,10 @@ { JNI_COCOA_ENTER(env); - NSURL *url = [NSURL URLWithString:JNFNormalizedNSStringForPath(env, urlString)]; + NSURL *url = [NSURL URLWithString:NormalizedPathNSStringFromJavaString(env, urlString)]; // Radar 3208005: Run this on the main thread; file:// style URLs will hang otherwise. - [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ [[NSWorkspace sharedWorkspace] openURL:url]; }]; @@ -174,15 +171,15 @@ jstring filename = NULL; JNI_COCOA_ENTER(env); - NSString *resourceName = JNFNormalizedNSStringForPath(env, javaResourceName); - NSString *subDirectory = JNFNormalizedNSStringForPath(env, javaSubDirName); - NSString *typeName = JNFNormalizedNSStringForPath(env, javaTypeName); + NSString *resourceName = NormalizedPathNSStringFromJavaString(env, javaResourceName); + NSString *subDirectory = NormalizedPathNSStringFromJavaString(env, javaSubDirName); + NSString *typeName = NormalizedPathNSStringFromJavaString(env, javaTypeName); NSString *path = [[NSBundle mainBundle] pathForResource:resourceName ofType:typeName inDirectory:subDirectory]; - filename = JNFNormalizedJavaStringForPath(env, path); + filename = NormalizedPathJavaStringFromNSString(env, path); JNI_COCOA_EXIT(env); return filename; @@ -201,7 +198,7 @@ JNI_COCOA_ENTER(env); NSBundle *mainBundle = [NSBundle mainBundle]; - filename = JNFNormalizedJavaStringForPath(env, [mainBundle bundlePath]); + filename = NormalizedPathJavaStringFromNSString(env, [mainBundle bundlePath]); JNI_COCOA_EXIT(env); return filename; @@ -220,9 +217,9 @@ __block BOOL returnValue = NO; JNI_COCOA_ENTER(env); - NSString * path = JNFNormalizedNSStringForPath(env, fileName); + NSString * path = NormalizedPathNSStringFromJavaString(env, fileName); NSURL *url = [NSURL fileURLWithPath:path]; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ returnValue = [[NSFileManager defaultManager] trashItemAtURL:url resultingItemURL:nil @@ -246,8 +243,8 @@ __block jboolean returnValue = JNI_FALSE; JNI_COCOA_ENTER(env); - NSString *path = JNFNormalizedNSStringForPath(env, url); - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + NSString *path = NormalizedPathNSStringFromJavaString(env, url); + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ returnValue = [[NSWorkspace sharedWorkspace] selectFile:path inFileViewerRootedAtPath:@""]; }]; diff --git a/src/java.desktop/macosx/native/libosxapp/JNIUtilities.h b/src/java.desktop/macosx/native/libosxapp/JNIUtilities.h index 47560233406..41dd4c48b75 100644 --- a/src/java.desktop/macosx/native/libosxapp/JNIUtilities.h +++ b/src/java.desktop/macosx/native/libosxapp/JNIUtilities.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -237,4 +237,14 @@ [pool drain]; \ }; +/******** STRING CONVERSION SUPPORT *********/ + +JNIEXPORT NSString* JavaStringToNSString(JNIEnv *env, jstring jstr); + +JNIEXPORT jstring NSStringToJavaString(JNIEnv* env, NSString *str); + +JNIEXPORT NSString* NormalizedPathNSStringFromJavaString(JNIEnv *env, jstring pathStr); + +JNIEXPORT jstring NormalizedPathJavaStringFromNSString(JNIEnv* env, NSString *str); + #endif /* __JNIUTILITIES_H */ diff --git a/src/java.desktop/macosx/native/libosxapp/JNIUtilities.m b/src/java.desktop/macosx/native/libosxapp/JNIUtilities.m new file mode 100644 index 00000000000..75d17803282 --- /dev/null +++ b/src/java.desktop/macosx/native/libosxapp/JNIUtilities.m @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "JNIUtilities.h" + +NSString* JavaStringToNSString(JNIEnv *env, jstring jstr) { + if (jstr == NULL) { + return NULL; + } + jsize len = (*env)->GetStringLength(env, jstr); + const jchar *chars = (*env)->GetStringChars(env, jstr, NULL); + if (chars == NULL) { + return NULL; + } + NSString *result = [NSString stringWithCharacters:(UniChar *)chars length:len]; + (*env)->ReleaseStringChars(env, jstr, chars); + return result; +} + +jstring NSStringToJavaString(JNIEnv* env, NSString *str) { + + if (str == NULL) { + return NULL; + } + jstring jStr = (*env)->NewStringUTF(env, [str UTF8String]); + CHECK_EXCEPTION(); + return jStr; +} + +/* + * These next conversion functions are for file system paths. + * The NSString needs to be in de-composed UTF-16 format for the Apple file system + * The Java String needs to be in pre-composed UTF-16 format for display by Java. + * https://developer.apple.com/library/archive/qa/qa1235/_index.html + * has some information on this. + */ + +/* + * Returns an NSString in decomposed UTF16 format that is compatible with HFS's + * expectation of the UTF16 format for file system paths. + * + * Example string: "/Users/Amélie/" + * + * Java's UTF16 string is "/ U s e r s / A m \351 l i e /" + * macOS UTF16 string suitable for HFS is "/ U s e r s / A m e \314 \201 l i e /" + * + * There is no direct API that takes in NSString UTF16 encoded by Java + * and produces NSString UTF16 for HFS, so we first need to decompose it + * into chars (suitable for low level C file APIs), and only then + * create NSString representation of this decomposition back into UTF16 string. + * + * https://developer.apple.com/documentation/foundation/nsstring/1414559-filesystemrepresentation?language=objc + * describes how to get a file system representation as a char* from an NSString + * and then using FileManager (!) convert it to an NSString. + * But we want an NSString. + * So the steps are + * 1) Convert to NSString + * 2) call [NSString fileSystemRepresentation] which gives us a char* + * 3) Convert the returned char* to an NSString using FileManager (is there a better way?) + */ +NSString* NormalizedPathNSStringFromJavaString(JNIEnv *env, jstring pathStr) { + if (pathStr == NULL) { + return nil; + } + NSString *nsStr = JavaStringToNSString(env, pathStr); + if (nsStr == NULL) { + return nil; + } + const char* chs = [nsStr fileSystemRepresentation]; + int len = strlen(chs); + NSString* result = [[NSFileManager defaultManager] + stringWithFileSystemRepresentation:chs length:len]; + return result; +} + +/* + * Given what is (potentially) a de-composed NSString, convert it to pre-composed + * Then convert it into a Java String. + */ +jstring NormalizedPathJavaStringFromNSString(JNIEnv* env, NSString *str) { + if (str == nil) { + return NULL; + } + NSString *normStr = [str precomposedStringWithCanonicalMapping]; + return NSStringToJavaString(env, normStr); +} diff --git a/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h b/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h index 888621604f3..0bf8cf75aff 100644 --- a/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h +++ b/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.h @@ -23,14 +23,8 @@ * questions. */ -/* - * Must include this before JavaNativeFoundation.h to get jni.h from build - */ -#include "jni.h" -#include "jni_util.h" - +#import "JNIUtilities.h" #import -#import JNIEXPORT @interface NSApplicationAWT : NSApplication { NSString *fApplicationName; diff --git a/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m b/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m index 4cb5bc0ca57..808814612c5 100644 --- a/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m +++ b/src/java.desktop/macosx/native/libosxapp/NSApplicationAWT.m @@ -160,9 +160,6 @@ - (void)finishLaunching [super finishLaunching]; [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self]; - - // inform any interested parties that the AWT has arrived and is pumping - [[NSNotificationCenter defaultCenter] postNotificationName:JNFRunLoopDidStartNotification object:self]; } - (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center @@ -271,7 +268,7 @@ - (void) registerWithProcessManager // HACK BEGIN // The following is necessary to make the java process behave like a // proper foreground application... - [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ ProcessSerialNumber psn; GetCurrentProcess(&psn); TransformProcessType(&psn, kProcessTransformToForegroundApplication); @@ -326,8 +323,8 @@ - (void) setDockIconWithEnv:(JNIEnv *)env { + (void) runAWTLoopWithApp:(NSApplication*)app { NSAutoreleasePool *pool = [NSAutoreleasePool new]; - // Make sure that when we run in AWTRunLoopMode we don't exit randomly - [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:[JNFRunLoop javaRunLoopMode]]; + // Make sure that when we run in javaRunLoopMode we don't exit randomly + [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:[ThreadUtilities javaRunLoopMode]]; do { @try { diff --git a/src/java.desktop/macosx/native/libosxapp/PropertiesUtilities.h b/src/java.desktop/macosx/native/libosxapp/PropertiesUtilities.h index ecf810de8c9..39af308b4e4 100644 --- a/src/java.desktop/macosx/native/libosxapp/PropertiesUtilities.h +++ b/src/java.desktop/macosx/native/libosxapp/PropertiesUtilities.h @@ -23,14 +23,10 @@ * questions. */ -/* - * Must include this before JavaNativeFoundation.h to get jni.h from build - */ #include "jni.h" #include "jni_util.h" #import -#import JNIEXPORT @interface PropertiesUtilities : NSObject diff --git a/src/java.desktop/macosx/native/libosxapp/PropertiesUtilities.m b/src/java.desktop/macosx/native/libosxapp/PropertiesUtilities.m index f727e2e22b9..10b0e00ed39 100644 --- a/src/java.desktop/macosx/native/libosxapp/PropertiesUtilities.m +++ b/src/java.desktop/macosx/native/libosxapp/PropertiesUtilities.m @@ -33,12 +33,12 @@ + (NSString *) javaSystemPropertyForKey:(NSString *)key withEnv:(JNIEnv *)env { DECLARE_STATIC_METHOD_RETURN(jm_getProperty, jc_System, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;", nil); - jstring jKey = JNFNSToJavaString(env, key); + jstring jKey = NSStringToJavaString(env, key); jstring jValue = (*env)->CallStaticObjectMethod(env, jc_System, jm_getProperty, jKey); (*env)->DeleteLocalRef(env, jKey); CHECK_EXCEPTION_NULL_RETURN(jValue, nil); - NSString *value = JNFJavaToNSString(env, jValue); + NSString *value = JavaStringToNSString(env, jValue); (*env)->DeleteLocalRef(env, jValue); return value; } diff --git a/src/java.desktop/macosx/native/libosxapp/ThreadUtilities.h b/src/java.desktop/macosx/native/libosxapp/ThreadUtilities.h index 4e99274578f..24fb2f61d86 100644 --- a/src/java.desktop/macosx/native/libosxapp/ThreadUtilities.h +++ b/src/java.desktop/macosx/native/libosxapp/ThreadUtilities.h @@ -125,16 +125,16 @@ do { \ // -------------------------------------------------------------------------- __attribute__((visibility("default"))) -@interface ThreadUtilities { } +@interface ThreadUtilities : NSObject { } /* Extend NSObject so can call performSelectorOnMainThread */ + (JNIEnv*)getJNIEnv; + (JNIEnv*)getJNIEnvUncached; + (void)detachCurrentThread; + (void)setAppkitThreadGroup:(jobject)group; -//Wrappers for the corresponding JNFRunLoop methods with a check for main thread + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block; + (void)performOnMainThread:(SEL)aSelector on:(id)target withObject:(id)arg waitUntilDone:(BOOL)wait; ++ (NSString*)javaRunLoopMode; @end JNIEXPORT void OSXAPP_SetJavaVM(JavaVM *vm); diff --git a/src/java.desktop/macosx/native/libosxapp/ThreadUtilities.m b/src/java.desktop/macosx/native/libosxapp/ThreadUtilities.m index 95443bcc73d..74be17039c3 100644 --- a/src/java.desktop/macosx/native/libosxapp/ThreadUtilities.m +++ b/src/java.desktop/macosx/native/libosxapp/ThreadUtilities.m @@ -24,7 +24,6 @@ */ #import -#import #import #import "ThreadUtilities.h" @@ -34,6 +33,8 @@ JavaVM *jvm = NULL; static JNIEnv *appKitEnv = NULL; static jobject appkitThreadGroup = NULL; +static NSString* JavaRunLoopMode = @"javaRunLoopMode"; +static NSArray *javaModes = nil; static inline void attachCurrentThread(void** env) { if ([NSThread isMainThread]) { @@ -49,6 +50,15 @@ static inline void attachCurrentThread(void** env) { @implementation ThreadUtilities ++ (void)initialize { + /* All the standard modes plus ours */ + javaModes = [[NSArray alloc] initWithObjects:NSDefaultRunLoopMode, + NSModalPanelRunLoopMode, + NSEventTrackingRunLoopMode, + JavaRunLoopMode, + nil]; +} + + (JNIEnv*)getJNIEnv { AWT_ASSERT_APPKIT_THREAD; if (appKitEnv == NULL) { @@ -71,11 +81,34 @@ + (void)setAppkitThreadGroup:(jobject)group { appkitThreadGroup = group; } +/* This is needed because we can't directly pass a block to + * performSelectorOnMainThreadWaiting .. since it expects a selector + */ ++ (void)invokeBlock:(void (^)())block { + block(); +} + +/* + * When running a block where either we don't wait, or it needs to run on another thread + * we need to copy it from stack to heap, use the copy in the call and release after use. + * Do this only when we must because it could be expensive. + * Note : if waiting cross-thread, possibly the stack allocated copy is accessible ? + */ ++ (void)invokeBlockCopy:(void (^)(void))blockCopy { + blockCopy(); + Block_release(blockCopy); +} + + (void)performOnMainThreadWaiting:(BOOL)wait block:(void (^)())block { if ([NSThread isMainThread] && wait == YES) { block(); } else { - [JNFRunLoop performOnMainThreadWaiting:wait withBlock:block]; + if (wait == YES) { + [self performOnMainThread:@selector(invokeBlock:) on:self withObject:block waitUntilDone:YES]; + } else { + void (^blockCopy)(void) = Block_copy(block); + [self performOnMainThread:@selector(invokeBlockCopy:) on:self withObject:blockCopy waitUntilDone:NO]; + } } } @@ -83,10 +116,14 @@ + (void)performOnMainThread:(SEL)aSelector on:(id)target withObject:(id)arg wait if ([NSThread isMainThread] && wait == YES) { [target performSelector:aSelector withObject:arg]; } else { - [JNFRunLoop performOnMainThread:aSelector on:target withObject:arg waitUntilDone:wait]; + [target performSelectorOnMainThread:aSelector withObject:arg waitUntilDone:wait modes:javaModes]; } } ++ (NSString*)javaRunLoopMode { + return JavaRunLoopMode; +} + @end diff --git a/src/java.desktop/macosx/native/libosxui/AquaFileView.m b/src/java.desktop/macosx/native/libosxui/AquaFileView.m index b8e8c7f734f..479d0cacb54 100644 --- a/src/java.desktop/macosx/native/libosxui/AquaFileView.m +++ b/src/java.desktop/macosx/native/libosxui/AquaFileView.m @@ -30,7 +30,6 @@ #import // for MAXPATHLEN #import -#import /* * Class: com_apple_laf_AquaFileView @@ -44,7 +43,7 @@ jstring returnValue = NULL; JNI_COCOA_ENTER(env); - returnValue = JNFNSToJavaString(env, getRunningJavaBundle()); + returnValue = NSStringToJavaString(env, getRunningJavaBundle()); JNI_COCOA_EXIT(env); return returnValue; @@ -61,7 +60,7 @@ jstring returnValue = NULL; JNI_COCOA_ENTER(env); - returnValue = JNFNSToJavaString(env, [[NSBundle bundleWithIdentifier:@"com.apple.JavaVM"] bundlePath]); + returnValue = NSStringToJavaString(env, [[NSBundle bundleWithIdentifier:@"com.apple.JavaVM"] bundlePath]); JNI_COCOA_EXIT(env); return returnValue; @@ -79,7 +78,7 @@ JNI_COCOA_ENTER(env); CFStringRef machineName = CSCopyMachineName(); - returnValue = JNFNSToJavaString(env, (NSString*)machineName); + returnValue = NSStringToJavaString(env, (NSString*)machineName); if (machineName != NULL) { CFRelease(machineName); @@ -169,7 +168,7 @@ if (theErr == noErr) { CFMutableStringRef mutableDisplayName = CFStringCreateMutableCopy(NULL, 0, displayName); CFStringNormalize(mutableDisplayName, kCFStringNormalizationFormC); - returnValue = JNFNSToJavaString(env, (NSString *)mutableDisplayName); + returnValue = NSStringToJavaString(env, (NSString *)mutableDisplayName); CFRelease(mutableDisplayName); } diff --git a/src/java.desktop/macosx/native/libosxui/AquaLookAndFeel.m b/src/java.desktop/macosx/native/libosxui/AquaLookAndFeel.m index 50ac4ba51e2..2cfd5b7118a 100644 --- a/src/java.desktop/macosx/native/libosxui/AquaLookAndFeel.m +++ b/src/java.desktop/macosx/native/libosxui/AquaLookAndFeel.m @@ -23,12 +23,9 @@ * questions. */ -// Must include this before JavaNativeFoundation.h to get jni.h from build #include "jni.h" #include "jni_util.h" -#import - /* * Empty JNI_OnLoad - needed to prevent: * AWT's JNI_OnLoad called multiple times diff --git a/src/java.desktop/macosx/native/libosxui/AquaNativeResources.m b/src/java.desktop/macosx/native/libosxui/AquaNativeResources.m index 474e57f7fc4..27128ea43fa 100644 --- a/src/java.desktop/macosx/native/libosxui/AquaNativeResources.m +++ b/src/java.desktop/macosx/native/libosxui/AquaNativeResources.m @@ -26,7 +26,6 @@ #import "com_apple_laf_AquaNativeResources.h" #import -#import /* * Class: com_apple_laf_AquaNativeResources diff --git a/src/java.desktop/macosx/native/libosxui/JRSUIConstantSync.m b/src/java.desktop/macosx/native/libosxui/JRSUIConstantSync.m index b3fc9f1e3e3..de5e8b26a76 100644 --- a/src/java.desktop/macosx/native/libosxui/JRSUIConstantSync.m +++ b/src/java.desktop/macosx/native/libosxui/JRSUIConstantSync.m @@ -23,7 +23,7 @@ * questions. */ -#import +#import "JNIUtilities.h" #import #import "apple_laf_JRSUIConstants.h" diff --git a/src/java.desktop/macosx/native/libosxui/JRSUIController.m b/src/java.desktop/macosx/native/libosxui/JRSUIController.m index 0f92f43fe8a..b484319b06e 100644 --- a/src/java.desktop/macosx/native/libosxui/JRSUIController.m +++ b/src/java.desktop/macosx/native/libosxui/JRSUIController.m @@ -23,7 +23,7 @@ * questions. */ -#import +#import "JNIUtilities.h" #import #import "apple_laf_JRSUIControl.h" diff --git a/src/java.desktop/macosx/native/libosxui/JRSUIFocus.m b/src/java.desktop/macosx/native/libosxui/JRSUIFocus.m index c5dca665d17..89741dfe332 100644 --- a/src/java.desktop/macosx/native/libosxui/JRSUIFocus.m +++ b/src/java.desktop/macosx/native/libosxui/JRSUIFocus.m @@ -23,7 +23,7 @@ * questions. */ -#import +#import "JNIUtilities.h" #import "apple_laf_JRSUIFocus.h" #import "apple_laf_JRSUIControl.h" diff --git a/src/java.desktop/macosx/native/libosxui/ScreenMenu.h b/src/java.desktop/macosx/native/libosxui/ScreenMenu.h index 65f3d85bc23..21402d68315 100644 --- a/src/java.desktop/macosx/native/libosxui/ScreenMenu.h +++ b/src/java.desktop/macosx/native/libosxui/ScreenMenu.h @@ -25,4 +25,3 @@ #import #import -#import diff --git a/src/java.desktop/macosx/native/libosxui/ScreenMenu.m b/src/java.desktop/macosx/native/libosxui/ScreenMenu.m index 1a19f03fce5..752f424c3d1 100644 --- a/src/java.desktop/macosx/native/libosxui/ScreenMenu.m +++ b/src/java.desktop/macosx/native/libosxui/ScreenMenu.m @@ -31,7 +31,6 @@ #import "java_awt_event_InputEvent.h" #import "java_awt_event_MouseEvent.h" -#import #import #import "ThreadUtilities.h" @@ -109,7 +108,7 @@ - (void)menuWillOpen:(NSMenu *)menu //NSLog(@"menuWillOpen %@", [menu title]); GET_SCREENMENU_CLASS(); DECLARE_METHOD(jm_ScreenMenu_invokeOpenLater, sjc_ScreenMenu, "invokeOpenLater", "()V"); - (*env)->CallVoidMethod(env, self.javaObject, jm_ScreenMenu_invokeOpenLater); // AWT_THREADING Safe (AWTRunLoopMode) + (*env)->CallVoidMethod(env, self.javaObject, jm_ScreenMenu_invokeOpenLater); CHECK_EXCEPTION(); JNI_COCOA_EXIT(env); @@ -129,7 +128,7 @@ - (void)menuDidClose:(NSMenu *)menu //NSLog(@"menuDidClose %@", [menu title]); GET_SCREENMENU_CLASS(); DECLARE_METHOD(jm_ScreenMenu_invokeMenuClosing, sjc_ScreenMenu, "invokeMenuClosing", "()V"); - (*env)->CallVoidMethod(env, self.javaObject, jm_ScreenMenu_invokeMenuClosing); // AWT_THREADING Safe (AWTRunLoopMode) + (*env)->CallVoidMethod(env, self.javaObject, jm_ScreenMenu_invokeMenuClosing); CHECK_EXCEPTION(); JNI_COCOA_EXIT(env); } @@ -150,12 +149,22 @@ - (void)handleJavaMenuItemTargetedAtIndex:(NSUInteger)menuIndex rect:(NSRect)rec GET_SCREENMENU_CLASS(); DECLARE_METHOD(jm_ScreenMenu_updateSelectedItem, sjc_ScreenMenu, "handleItemTargeted", "(IIIII)V"); (*env)->CallVoidMethod(env, self.javaObject, jm_ScreenMenu_updateSelectedItem, menuIndex, - NSMinY(rect), NSMinX(rect), NSMaxY(rect), NSMaxX(rect)); // AWT_THREADING Safe (AWTRunLoopMode) + NSMinY(rect), NSMinX(rect), NSMaxY(rect), NSMaxX(rect)); CHECK_EXCEPTION(); JNI_COCOA_EXIT(env); } +/* + * The input is an NSTimeInterval (a double representing seconds and fractions of seconds) + * 0.0 means midnight Jan 1, 2001. + * The output is a Java long representing time in milliseconds since midnight Jan 1st 1970. + * There is a Cocoa constant representing that difference : NSTimeIntervalSince1970 + */ +static jlong NSTimeIntervalToJavaMilliseconds(NSTimeInterval interval) { + NSTimeInterval interval1970 = interval + NSTimeIntervalSince1970; + return (jlong)(interval1970 * 1000); +} // Called from event handler callback - (void)handleJavaMouseEvent:(NSEvent *)event @@ -187,7 +196,7 @@ - (void)handleJavaMouseEvent:(NSEvent *)event jint javaModifiers = ns2awtModifiers([event modifierFlags]) | ns2awtMouseButton([event buttonNumber]); // Get the event time - jlong javaWhen = JNFNSTimeIntervalToJavaMillis([event timestamp]); + jlong javaWhen = NSTimeIntervalToJavaMilliseconds([event timestamp]); // Call the mouse event handler, which will generate Java mouse events. JNIEnv *env = [ThreadUtilities getJNIEnv]; @@ -195,7 +204,7 @@ - (void)handleJavaMouseEvent:(NSEvent *)event GET_SCREENMENU_CLASS(); DECLARE_METHOD(jm_ScreenMenu_handleMouseEvent, sjc_ScreenMenu, "handleMouseEvent", "(IIIIJ)V"); (*env)->CallVoidMethod(env, self.javaObject, jm_ScreenMenu_handleMouseEvent, - javaKind, javaX, javaY, javaModifiers, javaWhen); // AWT_THREADING Safe (AWTRunLoopMode) + javaKind, javaX, javaY, javaModifiers, javaWhen); CHECK_EXCEPTION(); JNI_COCOA_EXIT(env); } @@ -221,7 +230,7 @@ - (void)handleJavaMouseEvent:(NSEvent *)event delegate = [[[NativeToJavaDelegate alloc] initFromMenu:menu javaObj:listenerRef] autorelease]; CFRetain(delegate); // GC - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^{ + [ThreadUtilities performOnMainThreadWaiting:YES block:^{ NSMenu *menu = delegate.nsmenu; if ([menu isJavaMenu]) { [menu setDelegate:delegate]; @@ -248,7 +257,7 @@ - (void)handleJavaMouseEvent:(NSEvent *)event NativeToJavaDelegate *delegate = (NativeToJavaDelegate *)jlong_to_ptr(fModelPtr); - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^{ + [ThreadUtilities performOnMainThreadWaiting:YES block:^{ NSMenu *menu = delegate.nsmenu; [menu setJavaMenuDelegate:nil]; [menu setDelegate:nil]; diff --git a/src/java.desktop/macosx/native/libsplashscreen/splashscreen_sys.m b/src/java.desktop/macosx/native/libsplashscreen/splashscreen_sys.m index 8750786b539..c28fe904102 100644 --- a/src/java.desktop/macosx/native/libsplashscreen/splashscreen_sys.m +++ b/src/java.desktop/macosx/native/libsplashscreen/splashscreen_sys.m @@ -29,7 +29,6 @@ #import #include -#import #import "NSApplicationAWT.h" #include @@ -226,7 +225,7 @@ static int isInAquaSession() { // If we are running SWT we should not start a runLoop if (!isSWTRunning()) { - [JNFRunLoop performOnMainThreadWaiting:NO withBlock:^() { + [ThreadUtilities performOnMainThreadWaiting:NO block:^() { [NSApplicationAWT runAWTLoopWithApp:[NSApplicationAWT sharedApplication]]; }]; } @@ -243,7 +242,7 @@ static int isInAquaSession() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; pthread_mutex_destroy(&splash->lock); - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ if (splash->window) { [splash->window orderOut:nil]; [splash->window release]; @@ -282,7 +281,7 @@ static int isInAquaSession() { SplashRedrawWindow(Splash * splash) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ // drop the reference to the old view and image [splash->window setContentView: nil]; SplashUpdateScreenData(splash); @@ -341,7 +340,7 @@ static int isInAquaSession() { void SplashReconfigureNow(Splash * splash) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ SplashCenter(splash); if (!splash->window) { @@ -430,7 +429,7 @@ void SplashReconfigureNow(Splash * splash) { fcntl(splash->controlpipe[0], F_GETFL, 0) | O_NONBLOCK); splash->time = SplashTime(); splash->currentFrame = 0; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ SplashCenter(splash); splash->window = (void*) [[NSWindow alloc] @@ -445,7 +444,7 @@ void SplashReconfigureNow(Splash * splash) { }]; fflush(stdout); if (splash->window) { - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + [ThreadUtilities performOnMainThreadWaiting:YES block:^(){ [splash->window orderFrontRegardless]; }]; SplashRedrawWindow(splash); diff --git a/src/java.desktop/share/classes/java/awt/BasicStroke.java b/src/java.desktop/share/classes/java/awt/BasicStroke.java index e74753265e3..cd68105186e 100644 --- a/src/java.desktop/share/classes/java/awt/BasicStroke.java +++ b/src/java.desktop/share/classes/java/awt/BasicStroke.java @@ -294,6 +294,7 @@ public BasicStroke() { * stroked outline of a specified {@code Shape}. * @param s the {@code Shape} boundary be stroked * @return the {@code Shape} of the stroked outline. + * @throws NullPointerException if {@code s} is {@code null} */ public Shape createStrokedShape(Shape s) { sun.java2d.pipe.RenderingEngine re = diff --git a/src/java.desktop/share/classes/java/awt/Graphics.java b/src/java.desktop/share/classes/java/awt/Graphics.java index fe8437f029e..234b474764e 100644 --- a/src/java.desktop/share/classes/java/awt/Graphics.java +++ b/src/java.desktop/share/classes/java/awt/Graphics.java @@ -193,6 +193,7 @@ public Graphics create(int x, int y, int width, int height) { * Sets this graphics context's current color to the specified * color. All subsequent graphics operations using this graphics * context use this specified color. + * A null argument is silently ignored. * @param c the new rendering color. * @see java.awt.Color * @see java.awt.Graphics#getColor 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 89fd39c565d..501ddafc684 100644 --- a/src/java.desktop/share/classes/java/awt/color/ColorSpace.java +++ b/src/java.desktop/share/classes/java/awt/color/ColorSpace.java @@ -39,8 +39,6 @@ import java.io.Serializable; import java.lang.annotation.Native; -import sun.java2d.cmm.CMSManager; - /** * This abstract class is used to serve as a color space tag to identify the * specific color space of a {@code Color} object or, via a {@code ColorModel} @@ -112,12 +110,22 @@ public abstract class ColorSpace implements Serializable { private final int numComponents; private transient String [] compName = null; - // Cache of singletons for the predefined color spaces. - private static ColorSpace sRGBspace; - private static ColorSpace XYZspace; - private static ColorSpace PYCCspace; - private static ColorSpace GRAYspace; - private static ColorSpace LINEAR_RGBspace; + /** + * The lazy cache of singletons for the predefined built-in color spaces. + */ + private interface BuiltInSpace { + + ColorSpace SRGB = new ICC_ColorSpace(ICC_Profile.getInstance(CS_sRGB)); + + ColorSpace LRGB = + new ICC_ColorSpace(ICC_Profile.getInstance(CS_LINEAR_RGB)); + + ColorSpace XYZ = new ICC_ColorSpace(ICC_Profile.getInstance(CS_CIEXYZ)); + + ColorSpace PYCC = new ICC_ColorSpace(ICC_Profile.getInstance(CS_PYCC)); + + ColorSpace GRAY = new ICC_ColorSpace(ICC_Profile.getInstance(CS_GRAY)); + } /** * Any of the family of XYZ color spaces. @@ -289,88 +297,24 @@ protected ColorSpace(int type, int numComponents) { * Returns a {@code ColorSpace} representing one of the specific predefined * color spaces. * - * @param colorspace a specific color space identified by one of the - * predefined class constants (e.g. {@code CS_sRGB}, - * {@code CS_LINEAR_RGB}, {@code CS_CIEXYZ}, {@code CS_GRAY}, or - * {@code CS_PYCC}) + * @param cspace a specific color space identified by one of the predefined + * class constants (e.g. {@code CS_sRGB}, {@code CS_LINEAR_RGB}, + * {@code CS_CIEXYZ}, {@code CS_GRAY}, or {@code CS_PYCC}) * @return the requested {@code ColorSpace} object */ // NOTE: This method may be called by privileged threads. // DO NOT INVOKE CLIENT CODE ON THIS THREAD! - public static ColorSpace getInstance (int colorspace) - { - ColorSpace theColorSpace; - - switch (colorspace) { - case CS_sRGB: - synchronized(ColorSpace.class) { - if (sRGBspace == null) { - ICC_Profile theProfile = ICC_Profile.getInstance (CS_sRGB); - sRGBspace = new ICC_ColorSpace (theProfile); - } - - theColorSpace = sRGBspace; + public static ColorSpace getInstance(int cspace) { + return switch (cspace) { + case CS_sRGB -> BuiltInSpace.SRGB; + case CS_LINEAR_RGB -> BuiltInSpace.LRGB; + case CS_CIEXYZ -> BuiltInSpace.XYZ; + case CS_PYCC -> BuiltInSpace.PYCC; + case CS_GRAY -> BuiltInSpace.GRAY; + default -> { + throw new IllegalArgumentException("Unknown color space"); } - break; - - case CS_CIEXYZ: - synchronized(ColorSpace.class) { - if (XYZspace == null) { - ICC_Profile theProfile = - ICC_Profile.getInstance (CS_CIEXYZ); - XYZspace = new ICC_ColorSpace (theProfile); - } - - theColorSpace = XYZspace; - } - break; - - case CS_PYCC: - synchronized(ColorSpace.class) { - if (PYCCspace == null) { - ICC_Profile theProfile = ICC_Profile.getInstance (CS_PYCC); - PYCCspace = new ICC_ColorSpace (theProfile); - } - - theColorSpace = PYCCspace; - } - break; - - - case CS_GRAY: - synchronized(ColorSpace.class) { - if (GRAYspace == null) { - ICC_Profile theProfile = ICC_Profile.getInstance (CS_GRAY); - GRAYspace = new ICC_ColorSpace (theProfile); - /* to allow access from java.awt.ColorModel */ - CMSManager.GRAYspace = GRAYspace; - } - - theColorSpace = GRAYspace; - } - break; - - - case CS_LINEAR_RGB: - synchronized(ColorSpace.class) { - if (LINEAR_RGBspace == null) { - ICC_Profile theProfile = - ICC_Profile.getInstance(CS_LINEAR_RGB); - LINEAR_RGBspace = new ICC_ColorSpace (theProfile); - /* to allow access from java.awt.ColorModel */ - CMSManager.LINEAR_RGBspace = LINEAR_RGBspace; - } - - theColorSpace = LINEAR_RGBspace; - } - break; - - - default: - throw new IllegalArgumentException ("Unknown color space"); - } - - return theColorSpace; + }; } /** @@ -380,8 +324,7 @@ public static ColorSpace getInstance (int colorspace) * {@code false} if it is not */ public boolean isCS_sRGB () { - /* REMIND - make sure we know sRGBspace exists already */ - return (this == sRGBspace); + return this == BuiltInSpace.SRGB; } /** diff --git a/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java b/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java index 967d96861f4..9b0d484d643 100644 --- a/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java +++ b/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java @@ -94,14 +94,31 @@ public class ICC_Profile implements Serializable { private transient volatile Profile cmmProfile; private transient volatile ProfileDeferralInfo deferralInfo; - // Registry of singleton profile objects for specific color spaces - // defined in the ColorSpace class (e.g. CS_sRGB), see - // getInstance(int cspace) factory method. - private static ICC_Profile sRGBprofile; - private static ICC_Profile XYZprofile; - private static ICC_Profile PYCCprofile; - private static ICC_Profile GRAYprofile; - private static ICC_Profile LINEAR_RGBprofile; + /** + * The lazy registry of singleton profile objects for specific built-in + * color spaces defined in the ColorSpace class (e.g. CS_sRGB), + * see getInstance(int cspace) factory method. + */ + private interface BuiltInProfile { + /* + * Deferral is only used for standard profiles. Enabling the appropriate + * access privileges is handled at a lower level. + */ + ICC_Profile SRGB = new ICC_ProfileRGB(new ProfileDeferralInfo( + "sRGB.pf", ColorSpace.TYPE_RGB, 3, CLASS_DISPLAY)); + + ICC_Profile LRGB = new ICC_ProfileRGB(new ProfileDeferralInfo( + "LINEAR_RGB.pf", ColorSpace.TYPE_RGB, 3, CLASS_DISPLAY)); + + ICC_Profile XYZ = new ICC_Profile(new ProfileDeferralInfo( + "CIEXYZ.pf", ColorSpace.TYPE_XYZ, 3, CLASS_ABSTRACT)); + + ICC_Profile PYCC = new ICC_Profile(new ProfileDeferralInfo( + "PYCC.pf", ColorSpace.TYPE_3CLR, 3, CLASS_COLORSPACECONVERSION)); + + ICC_Profile GRAY = new ICC_ProfileGray(new ProfileDeferralInfo( + "GRAY.pf", ColorSpace.TYPE_GRAY, 1, CLASS_DISPLAY)); + } /** * Profile class is input. @@ -758,12 +775,13 @@ protected void finalize () { /** * Constructs an {@code ICC_Profile} object corresponding to the data in a - * byte array. Throws an {@code IllegalArgumentException} if the data does - * not correspond to a valid ICC Profile. + * byte array. * * @param data the specified ICC Profile data * @return an {@code ICC_Profile} object corresponding to the data in the * specified {@code data} array + * @throws IllegalArgumentException If the byte array does not contain valid + * ICC Profile data */ public static ICC_Profile getInstance(byte[] data) { ICC_Profile thisProfile; @@ -817,89 +835,17 @@ else if ((getColorSpaceType (p) == ColorSpace.TYPE_RGB) && * @throws IllegalArgumentException If {@code cspace} is not one of the * predefined color space types */ - public static ICC_Profile getInstance (int cspace) { - ICC_Profile thisProfile = null; - switch (cspace) { - case ColorSpace.CS_sRGB: - synchronized(ICC_Profile.class) { - if (sRGBprofile == null) { - /* - * Deferral is only used for standard profiles. - * Enabling the appropriate access privileges is handled - * at a lower level. - */ - ProfileDeferralInfo pdi = - new ProfileDeferralInfo("sRGB.pf", - ColorSpace.TYPE_RGB, 3, - CLASS_DISPLAY); - sRGBprofile = new ICC_ProfileRGB(pdi); - } - thisProfile = sRGBprofile; - } - - break; - - case ColorSpace.CS_CIEXYZ: - synchronized(ICC_Profile.class) { - if (XYZprofile == null) { - ProfileDeferralInfo pdi = - new ProfileDeferralInfo("CIEXYZ.pf", - ColorSpace.TYPE_XYZ, 3, - CLASS_ABSTRACT); - XYZprofile = new ICC_Profile(pdi); - } - thisProfile = XYZprofile; + public static ICC_Profile getInstance(int cspace) { + return switch (cspace) { + case ColorSpace.CS_sRGB -> BuiltInProfile.SRGB; + case ColorSpace.CS_LINEAR_RGB -> BuiltInProfile.LRGB; + case ColorSpace.CS_CIEXYZ -> BuiltInProfile.XYZ; + case ColorSpace.CS_PYCC -> BuiltInProfile.PYCC; + case ColorSpace.CS_GRAY -> BuiltInProfile.GRAY; + default -> { + throw new IllegalArgumentException("Unknown color space"); } - - break; - - case ColorSpace.CS_PYCC: - synchronized(ICC_Profile.class) { - if (PYCCprofile == null) { - ProfileDeferralInfo pdi = - new ProfileDeferralInfo("PYCC.pf", - ColorSpace.TYPE_3CLR, 3, - CLASS_COLORSPACECONVERSION); - PYCCprofile = new ICC_Profile(pdi); - } - thisProfile = PYCCprofile; - } - - break; - - case ColorSpace.CS_GRAY: - synchronized(ICC_Profile.class) { - if (GRAYprofile == null) { - ProfileDeferralInfo pdi = - new ProfileDeferralInfo("GRAY.pf", - ColorSpace.TYPE_GRAY, 1, - CLASS_DISPLAY); - GRAYprofile = new ICC_ProfileGray(pdi); - } - thisProfile = GRAYprofile; - } - - break; - - case ColorSpace.CS_LINEAR_RGB: - synchronized(ICC_Profile.class) { - if (LINEAR_RGBprofile == null) { - ProfileDeferralInfo pdi = - new ProfileDeferralInfo("LINEAR_RGB.pf", - ColorSpace.TYPE_RGB, 3, - CLASS_DISPLAY); - LINEAR_RGBprofile = new ICC_ProfileRGB(pdi); - } - thisProfile = LINEAR_RGBprofile; - } - - break; - - default: - throw new IllegalArgumentException("Unknown color space"); - } - - return thisProfile; + }; } /** @@ -927,10 +873,7 @@ public static ICC_Profile getInstance (int cspace) { * not permit read access to the given file */ public static ICC_Profile getInstance(String fileName) throws IOException { - ICC_Profile thisProfile; - InputStream is = null; - - + InputStream is; File f = getProfileFile(fileName); if (f != null) { is = new FileInputStream(f); @@ -940,12 +883,9 @@ public static ICC_Profile getInstance(String fileName) throws IOException { if (is == null) { throw new IOException("Cannot open file " + fileName); } - - thisProfile = getInstance(is); - - is.close(); /* close the file */ - - return thisProfile; + try (is) { + return getInstance(is); + } } /** @@ -963,22 +903,17 @@ public static ICC_Profile getInstance(String fileName) throws IOException { * Profile data */ public static ICC_Profile getInstance(InputStream s) throws IOException { - byte[] profileData; - if ((profileData = getProfileDataFromStream(s)) == null) { - throw new IllegalArgumentException("Invalid ICC Profile Data"); - } - - return getInstance(profileData); + return getInstance(getProfileDataFromStream(s)); } static byte[] getProfileDataFromStream(InputStream s) throws IOException { BufferedInputStream bis = new BufferedInputStream(s); - bis.mark(128); + bis.mark(128); // 128 is the length of the ICC profile header byte[] header = bis.readNBytes(128); - if (header[36] != 0x61 || header[37] != 0x63 || + if (header.length < 128 || header[36] != 0x61 || header[37] != 0x63 || header[38] != 0x73 || header[39] != 0x70) { return null; /* not a valid profile */ } @@ -1010,14 +945,13 @@ private void activate() { if (is == null) { return; } - try { + try (is) { byte[] data = getProfileDataFromStream(is); if (data != null) { cmmProfile = CMSManager.getModule().loadProfile(data); // from now we cannot use the deferred value, drop it deferralInfo = null; } - is.close(); /* close the stream */ } catch (CMMException | IOException ignore) { } } @@ -1174,14 +1108,9 @@ static int getPCSType(Profile p) { * error occurs while writing to the file */ public void write(String fileName) throws IOException { - FileOutputStream outputFile; - byte[] profileData; - - profileData = getData(); /* this will activate deferred - profiles if necessary */ - outputFile = new FileOutputStream(fileName); - outputFile.write(profileData); - outputFile.close (); + try (OutputStream out = new FileOutputStream(fileName)) { + write(out); + } } /** @@ -1191,11 +1120,7 @@ public void write(String fileName) throws IOException { * @throws IOException If an I/O error occurs while writing to the stream */ public void write(OutputStream s) throws IOException { - byte[] profileData; - - profileData = getData(); /* this will activate deferred - profiles if necessary */ - s.write(profileData); + s.write(getData()); } /** @@ -1823,15 +1748,15 @@ private void writeObject(ObjectOutputStream s) s.defaultWriteObject(); String csName = null; - if (this == sRGBprofile) { + if (this == BuiltInProfile.SRGB) { csName = "CS_sRGB"; - } else if (this == XYZprofile) { + } else if (this == BuiltInProfile.XYZ) { csName = "CS_CIEXYZ"; - } else if (this == PYCCprofile) { + } else if (this == BuiltInProfile.PYCC) { csName = "CS_PYCC"; - } else if (this == GRAYprofile) { + } else if (this == BuiltInProfile.GRAY) { csName = "CS_GRAY"; - } else if (this == LINEAR_RGBprofile) { + } else if (this == BuiltInProfile.LRGB) { csName = "CS_LINEAR_RGB"; } diff --git a/src/java.desktop/share/classes/java/awt/geom/Rectangle2D.java b/src/java.desktop/share/classes/java/awt/geom/Rectangle2D.java index 3431d0d60aa..b27bdce7f25 100644 --- a/src/java.desktop/share/classes/java/awt/geom/Rectangle2D.java +++ b/src/java.desktop/share/classes/java/awt/geom/Rectangle2D.java @@ -794,7 +794,7 @@ public static void union(Rectangle2D src1, * {@code true}. The {@code contains} method does not * return {@code true} for points on the right or bottom * edges of a rectangle. Therefore, if the added point falls on - * the left or bottom edge of the enlarged rectangle, + * the right or bottom edge of the enlarged rectangle, * {@code contains} returns {@code false} for that point. * @param newx the X coordinate of the new point * @param newy the Y coordinate of the new point @@ -820,7 +820,7 @@ public void add(double newx, double newy) { * {@code true}. The {@code contains} * method does not return {@code true} for points on the right * or bottom edges of a rectangle. Therefore, if the added point falls - * on the left or bottom edge of the enlarged rectangle, + * on the right or bottom edge of the enlarged rectangle, * {@code contains} returns {@code false} for that point. * @param pt the new {@code Point2D} to add to this * {@code Rectangle2D}. diff --git a/src/java.desktop/share/classes/java/awt/image/AreaAveragingScaleFilter.java b/src/java.desktop/share/classes/java/awt/image/AreaAveragingScaleFilter.java index a8e09a7435c..decfeb33622 100644 --- a/src/java.desktop/share/classes/java/awt/image/AreaAveragingScaleFilter.java +++ b/src/java.desktop/share/classes/java/awt/image/AreaAveragingScaleFilter.java @@ -72,6 +72,8 @@ public class AreaAveragingScaleFilter extends ReplicateScaleFilter { * its source Image as specified by the width and height parameters. * @param width the target width to scale the image * @param height the target height to scale the image + * @throws IllegalArgumentException if {@code width} equals + * zero or {@code height} equals zero */ public AreaAveragingScaleFilter(int width, int height) { super(width, height); diff --git a/src/java.desktop/share/classes/java/awt/image/ColorModel.java b/src/java.desktop/share/classes/java/awt/image/ColorModel.java index c4c8f80af7a..8f4dd445821 100644 --- a/src/java.desktop/share/classes/java/awt/image/ColorModel.java +++ b/src/java.desktop/share/classes/java/awt/image/ColorModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1705,15 +1705,11 @@ static int getDefaultTransferType(int pixel_bits) { static Map lg16Toog16Map = null; // 16-bit linear to 16-bit "other" gray static boolean isLinearRGBspace(ColorSpace cs) { - // Note: CMM.LINEAR_RGBspace will be null if the linear - // RGB space has not been created yet. - return (cs == CMSManager.LINEAR_RGBspace); + return cs == ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB); } static boolean isLinearGRAYspace(ColorSpace cs) { - // Note: CMM.GRAYspace will be null if the linear - // gray space has not been created yet. - return (cs == CMSManager.GRAYspace); + return cs == ColorSpace.getInstance(ColorSpace.CS_GRAY); } static byte[] getLinearRGB8TosRGB8LUT() { diff --git a/src/java.desktop/share/classes/javax/swing/JEditorPane.java b/src/java.desktop/share/classes/javax/swing/JEditorPane.java index df7f7bd990f..4a918294b5b 100644 --- a/src/java.desktop/share/classes/javax/swing/JEditorPane.java +++ b/src/java.desktop/share/classes/javax/swing/JEditorPane.java @@ -1621,7 +1621,7 @@ private void writeObject(ObjectOutputStream s) throws IOException { /** * Key for a client property used to indicate whether - * + * * w3c compliant length units are used for html rendering. *

    * By default this is not enabled; to enable diff --git a/src/java.desktop/share/classes/javax/swing/text/html/CSS.java b/src/java.desktop/share/classes/javax/swing/text/html/CSS.java index 4aa3eb6f42d..c14b5a126e4 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/CSS.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/CSS.java @@ -27,7 +27,6 @@ import java.awt.Color; import java.awt.Font; -import java.awt.HeadlessException; import java.awt.Image; import java.awt.Toolkit; import java.io.IOException; @@ -2881,18 +2880,14 @@ static class LengthUnit implements Serializable { lengthMapping.put("cm", 28.3464f); lengthMapping.put("pc", 12f); lengthMapping.put("in", 72f); - int res = 72; - try { - res = Toolkit.getDefaultToolkit().getScreenResolution(); - } catch (HeadlessException e) { - } - // mapping according to the CSS2 spec - w3cLengthMapping.put("pt", res / 72f); - w3cLengthMapping.put("px", 1f); - w3cLengthMapping.put("mm", res / 25.4f); - w3cLengthMapping.put("cm", res / 2.54f); - w3cLengthMapping.put("pc", res / 6f); - w3cLengthMapping.put("in", (float) res); + // Mapping according to the CSS2.2 spec + // https://www.w3.org/TR/CSS22/syndata.html#x39 + w3cLengthMapping.put("pt", 96f / 72f); // 1/72 of 1in + w3cLengthMapping.put("px", 1f); // 1/96 of 1in + w3cLengthMapping.put("mm", 96f / 2.54f / 10f); // 1/10 of 1cm + w3cLengthMapping.put("cm", 96f / 2.54f); // 96px/2.54 + w3cLengthMapping.put("pc", 96f / 6f); // 1/6 of 1in + w3cLengthMapping.put("in", 96f); // 96px } LengthUnit(String value, short defaultType, float defaultValue) { diff --git a/src/java.desktop/share/classes/javax/swing/text/html/StyleSheet.java b/src/java.desktop/share/classes/javax/swing/text/html/StyleSheet.java index ee2946b5938..3352e0e79f8 100644 --- a/src/java.desktop/share/classes/javax/swing/text/html/StyleSheet.java +++ b/src/java.desktop/share/classes/javax/swing/text/html/StyleSheet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2813,7 +2813,10 @@ public Object getAttribute(Object key) { ((StyleConstants)key); if (cssKey != null) { Object value = doGetAttribute(cssKey); - if (value instanceof CSS.CssValue) { + if (value instanceof CSS.FontSize) { + return ((CSS.FontSize)value) + .getValue(this, StyleSheet.this); + } else if (value instanceof CSS.CssValue) { return ((CSS.CssValue)value).toStyleConstants ((StyleConstants)key, host); } diff --git a/src/java.desktop/share/classes/sun/java2d/cmm/CMSManager.java b/src/java.desktop/share/classes/sun/java2d/cmm/CMSManager.java index 4d9f09c5905..024ea437e4f 100644 --- a/src/java.desktop/share/classes/sun/java2d/cmm/CMSManager.java +++ b/src/java.desktop/share/classes/sun/java2d/cmm/CMSManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,20 +26,12 @@ package sun.java2d.cmm; import java.awt.color.CMMException; -import java.awt.color.ColorSpace; import java.awt.color.ICC_Profile; import java.security.AccessController; import sun.security.action.GetPropertyAction; -public class CMSManager { - public static ColorSpace GRAYspace; // These two fields allow access - public static ColorSpace LINEAR_RGBspace; // to java.awt.color.ColorSpace - // private fields from other - // packages. The fields are set - // by java.awt.color.ColorSpace - // and read by - // java.awt.image.ColorModel. +public final class CMSManager { private static PCMM cmmImpl = null; diff --git a/src/java.desktop/share/legal/lcms.md b/src/java.desktop/share/legal/lcms.md index 0dce053fe55..1977a6b1597 100644 --- a/src/java.desktop/share/legal/lcms.md +++ b/src/java.desktop/share/legal/lcms.md @@ -1,4 +1,4 @@ -## Little Color Management System (LCMS) v2.11 +## Little Color Management System (LCMS) v2.12 ### LCMS License

    diff --git a/src/java.desktop/share/native/liblcms/cmsalpha.c b/src/java.desktop/share/native/liblcms/cmsalpha.c
    index 1b31782f47b..49ff22df764 100644
    --- a/src/java.desktop/share/native/liblcms/cmsalpha.c
    +++ b/src/java.desktop/share/native/liblcms/cmsalpha.c
    @@ -104,7 +104,7 @@ static
     void from8to16(void* dst, const void* src)
     {
            cmsUInt8Number n = *(cmsUInt8Number*)src;
    -       *(cmsUInt16Number*) dst = FROM_8_TO_16(n);
    +       *(cmsUInt16Number*) dst = (cmsUInt16Number) FROM_8_TO_16(n);
     }
     
     static
    @@ -117,13 +117,13 @@ void from8to16SE(void* dst, const void* src)
     static
     void from8toFLT(void* dst, const void* src)
     {
    -       *(cmsFloat32Number*)dst = (*(cmsUInt8Number*)src) / 255.0f;
    +       *(cmsFloat32Number*)dst = (cmsFloat32Number) (*(cmsUInt8Number*)src) / 255.0f;
     }
     
     static
     void from8toDBL(void* dst, const void* src)
     {
    -       *(cmsFloat64Number*)dst = (*(cmsUInt8Number*)src) / 255.0;
    +       *(cmsFloat64Number*)dst = (cmsFloat64Number) (*(cmsUInt8Number*)src) / 255.0;
     }
     
     static
    @@ -182,13 +182,13 @@ void from16SEtoFLT(void* dst, const void* src)
     static
     void from16toDBL(void* dst, const void* src)
     {
    -       *(cmsFloat64Number*)dst = (*(cmsUInt16Number*)src) / 65535.0f;
    +       *(cmsFloat64Number*)dst = (cmsFloat64Number) (*(cmsUInt16Number*)src) / 65535.0;
     }
     
     static
     void from16SEtoDBL(void* dst, const void* src)
     {
    -    *(cmsFloat64Number*)dst = (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0f;
    +    *(cmsFloat64Number*)dst = (cmsFloat64Number) (CHANGE_ENDIAN(*(cmsUInt16Number*)src)) / 65535.0;
     }
     
     static
    diff --git a/src/java.desktop/share/native/liblcms/cmscgats.c b/src/java.desktop/share/native/liblcms/cmscgats.c
    index a26b1cc0407..07109b1e449 100644
    --- a/src/java.desktop/share/native/liblcms/cmscgats.c
    +++ b/src/java.desktop/share/native/liblcms/cmscgats.c
    @@ -1525,6 +1525,14 @@ cmsBool CMSEXPORT cmsIT8SetDataFormat(cmsHANDLE  h, int n, const char *Sample)
         return SetDataFormat(it8, n, Sample);
     }
     
    +// A safe atoi that returns 0 when NULL input is given
    +static
    +cmsInt32Number satoi(const char* b)
    +{
    +    if (b == NULL) return 0;
    +    return atoi(b);
    +}
    +
     static
     void AllocateDataSet(cmsIT8* it8)
     {
    @@ -1532,14 +1540,15 @@ void AllocateDataSet(cmsIT8* it8)
     
         if (t -> Data) return;    // Already allocated
     
    -    t-> nSamples   = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
    -    t-> nPatches   = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
    +    t-> nSamples   = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
    +    t-> nPatches   = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
     
         if (t -> nSamples < 0 || t->nSamples > 0x7ffe || t->nPatches < 0 || t->nPatches > 0x7ffe)
         {
             SynError(it8, "AllocateDataSet: too much data");
         }
         else {
    +        // Some dumb analizers warns of possible overflow here, just take a look couple of lines above.
             t->Data = (char**)AllocChunk(it8, ((cmsUInt32Number)t->nSamples + 1) * ((cmsUInt32Number)t->nPatches + 1) * sizeof(char*));
             if (t->Data == NULL) {
     
    @@ -1705,11 +1714,11 @@ void WriteHeader(cmsIT8* it8, SAVESTREAM* fp)
                         break;
     
                 case WRITE_HEXADECIMAL:
    -                    Writef(fp, "\t0x%X", atoi(p ->Value));
    +                    Writef(fp, "\t0x%X", satoi(p ->Value));
                         break;
     
                 case WRITE_BINARY:
    -                    Writef(fp, "\t0x%B", atoi(p ->Value));
    +                    Writef(fp, "\t0x%B", satoi(p ->Value));
                         break;
     
                 case WRITE_PAIR:
    @@ -1738,7 +1747,7 @@ void WriteDataFormat(SAVESTREAM* fp, cmsIT8* it8)
     
            WriteStr(fp, "BEGIN_DATA_FORMAT\n");
            WriteStr(fp, " ");
    -       nSamples = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
    +       nSamples = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_FIELDS"));
     
            for (i = 0; i < nSamples; i++) {
     
    @@ -1761,7 +1770,7 @@ void WriteData(SAVESTREAM* fp, cmsIT8* it8)
     
            WriteStr (fp, "BEGIN_DATA\n");
     
    -       t->nPatches = atoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
    +       t->nPatches = satoi(cmsIT8GetProperty(it8, "NUMBER_OF_SETS"));
     
            for (i = 0; i < t-> nPatches; i++) {
     
    diff --git a/src/java.desktop/share/native/liblcms/cmscnvrt.c b/src/java.desktop/share/native/liblcms/cmscnvrt.c
    index fa1f8f09210..4bee13d6491 100644
    --- a/src/java.desktop/share/native/liblcms/cmscnvrt.c
    +++ b/src/java.desktop/share/native/liblcms/cmscnvrt.c
    @@ -759,6 +759,9 @@ cmsPipeline*  BlackPreservingKOnlyIntents(cmsContext     ContextID,
         cmsUInt32Number ICCIntents[256];
         cmsStage*         CLUT;
         cmsUInt32Number i, nGridPoints;
    +    cmsUInt32Number lastProfilePos;
    +    cmsUInt32Number preservationProfilesCount;
    +    cmsHPROFILE hLastProfile;
     
     
         // Sanity check
    @@ -768,20 +771,36 @@ cmsPipeline*  BlackPreservingKOnlyIntents(cmsContext     ContextID,
         for (i=0; i < nProfiles; i++)
             ICCIntents[i] = TranslateNonICCIntents(TheIntents[i]);
     
    +
    +    // Trim all CMYK devicelinks at the end
    +    lastProfilePos = nProfiles - 1;
    +    hLastProfile = hProfiles[lastProfilePos];
    +
    +    while (lastProfilePos > 1)
    +    {
    +        hLastProfile = hProfiles[--lastProfilePos];
    +        if (cmsGetColorSpace(hLastProfile) != cmsSigCmykData ||
    +            cmsGetDeviceClass(hLastProfile) != cmsSigLinkClass)
    +            break;
    +    }
    +
    +    preservationProfilesCount = lastProfilePos + 1;
    +
         // Check for non-cmyk profiles
         if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData ||
    -        cmsGetColorSpace(hProfiles[nProfiles-1]) != cmsSigCmykData)
    +        !(cmsGetColorSpace(hLastProfile) == cmsSigCmykData ||
    +        cmsGetDeviceClass(hLastProfile) == cmsSigOutputClass))
                return DefaultICCintents(ContextID, nProfiles, ICCIntents, hProfiles, BPC, AdaptationStates, dwFlags);
     
    -    memset(&bp, 0, sizeof(bp));
    -
         // Allocate an empty LUT for holding the result
         Result = cmsPipelineAlloc(ContextID, 4, 4);
         if (Result == NULL) return NULL;
     
    +    memset(&bp, 0, sizeof(bp));
    +
         // Create a LUT holding normal ICC transform
         bp.cmyk2cmyk = DefaultICCintents(ContextID,
    -        nProfiles,
    +                                     preservationProfilesCount,
             ICCIntents,
             hProfiles,
             BPC,
    @@ -793,7 +812,7 @@ cmsPipeline*  BlackPreservingKOnlyIntents(cmsContext     ContextID,
         // Now, compute the tone curve
         bp.KTone = _cmsBuildKToneCurve(ContextID,
             4096,
    -        nProfiles,
    +                                    preservationProfilesCount,
             ICCIntents,
             hProfiles,
             BPC,
    @@ -818,6 +837,19 @@ cmsPipeline*  BlackPreservingKOnlyIntents(cmsContext     ContextID,
         if (!cmsStageSampleCLut16bit(CLUT, BlackPreservingGrayOnlySampler, (void*) &bp, 0))
             goto Error;
     
    +
    +    // Insert possible devicelinks at the end
    +    for (i = lastProfilePos + 1; i < nProfiles; i++)
    +    {
    +        cmsPipeline* devlink = _cmsReadDevicelinkLUT(hProfiles[i], ICCIntents[i]);
    +        if (devlink == NULL)
    +            goto Error;
    +
    +        if (!cmsPipelineCat(Result, devlink))
    +            goto Error;
    +    }
    +
    +
         // Get rid of xform and tone curve
         cmsPipelineFree(bp.cmyk2cmyk);
         cmsFreeToneCurve(bp.KTone);
    @@ -936,6 +968,8 @@ int BlackPreservingSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER c
         return TRUE;
     }
     
    +
    +
     // This is the entry for black-plane preserving, which are non-ICC
     static
     cmsPipeline* BlackPreservingKPlaneIntents(cmsContext     ContextID,
    @@ -947,10 +981,14 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext     ContextID,
                                               cmsUInt32Number dwFlags)
     {
         PreserveKPlaneParams bp;
    +
         cmsPipeline*    Result = NULL;
         cmsUInt32Number ICCIntents[256];
         cmsStage*         CLUT;
         cmsUInt32Number i, nGridPoints;
    +    cmsUInt32Number lastProfilePos;
    +    cmsUInt32Number preservationProfilesCount;
    +    cmsHPROFILE hLastProfile;
         cmsHPROFILE hLab;
     
         // Sanity check
    @@ -960,32 +998,45 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext     ContextID,
         for (i=0; i < nProfiles; i++)
             ICCIntents[i] = TranslateNonICCIntents(TheIntents[i]);
     
    +    // Trim all CMYK devicelinks at the end
    +    lastProfilePos = nProfiles - 1;
    +    hLastProfile = hProfiles[lastProfilePos];
    +
    +    while (lastProfilePos > 1)
    +    {
    +        hLastProfile = hProfiles[--lastProfilePos];
    +        if (cmsGetColorSpace(hLastProfile) != cmsSigCmykData ||
    +            cmsGetDeviceClass(hLastProfile) != cmsSigLinkClass)
    +            break;
    +    }
    +
    +    preservationProfilesCount = lastProfilePos + 1;
    +
         // Check for non-cmyk profiles
         if (cmsGetColorSpace(hProfiles[0]) != cmsSigCmykData ||
    -        !(cmsGetColorSpace(hProfiles[nProfiles-1]) == cmsSigCmykData ||
    -        cmsGetDeviceClass(hProfiles[nProfiles-1]) == cmsSigOutputClass))
    +        !(cmsGetColorSpace(hLastProfile) == cmsSigCmykData ||
    +        cmsGetDeviceClass(hLastProfile) == cmsSigOutputClass))
                return  DefaultICCintents(ContextID, nProfiles, ICCIntents, hProfiles, BPC, AdaptationStates, dwFlags);
     
         // Allocate an empty LUT for holding the result
         Result = cmsPipelineAlloc(ContextID, 4, 4);
         if (Result == NULL) return NULL;
     
    -
         memset(&bp, 0, sizeof(bp));
     
         // We need the input LUT of the last profile, assuming this one is responsible of
         // black generation. This LUT will be searched in inverse order.
    -    bp.LabK2cmyk = _cmsReadInputLUT(hProfiles[nProfiles-1], INTENT_RELATIVE_COLORIMETRIC);
    +    bp.LabK2cmyk = _cmsReadInputLUT(hLastProfile, INTENT_RELATIVE_COLORIMETRIC);
         if (bp.LabK2cmyk == NULL) goto Cleanup;
     
         // Get total area coverage (in 0..1 domain)
    -    bp.MaxTAC = cmsDetectTAC(hProfiles[nProfiles-1]) / 100.0;
    +    bp.MaxTAC = cmsDetectTAC(hLastProfile) / 100.0;
         if (bp.MaxTAC <= 0) goto Cleanup;
     
     
         // Create a LUT holding normal ICC transform
         bp.cmyk2cmyk = DefaultICCintents(ContextID,
    -                                         nProfiles,
    +                                         preservationProfilesCount,
                                              ICCIntents,
                                              hProfiles,
                                              BPC,
    @@ -994,7 +1045,7 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext     ContextID,
         if (bp.cmyk2cmyk == NULL) goto Cleanup;
     
         // Now the tone curve
    -    bp.KTone = _cmsBuildKToneCurve(ContextID, 4096, nProfiles,
    +    bp.KTone = _cmsBuildKToneCurve(ContextID, 4096, preservationProfilesCount,
                                        ICCIntents,
                                        hProfiles,
                                        BPC,
    @@ -1004,14 +1055,14 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext     ContextID,
     
         // To measure the output, Last profile to Lab
         hLab = cmsCreateLab4ProfileTHR(ContextID, NULL);
    -    bp.hProofOutput = cmsCreateTransformTHR(ContextID, hProfiles[nProfiles-1],
    +    bp.hProofOutput = cmsCreateTransformTHR(ContextID, hLastProfile,
                                              CHANNELS_SH(4)|BYTES_SH(2), hLab, TYPE_Lab_DBL,
                                              INTENT_RELATIVE_COLORIMETRIC,
                                              cmsFLAGS_NOCACHE|cmsFLAGS_NOOPTIMIZE);
         if ( bp.hProofOutput == NULL) goto Cleanup;
     
         // Same as anterior, but lab in the 0..1 range
    -    bp.cmyk2Lab = cmsCreateTransformTHR(ContextID, hProfiles[nProfiles-1],
    +    bp.cmyk2Lab = cmsCreateTransformTHR(ContextID, hLastProfile,
                                              FLOAT_SH(1)|CHANNELS_SH(4)|BYTES_SH(4), hLab,
                                              FLOAT_SH(1)|CHANNELS_SH(3)|BYTES_SH(4),
                                              INTENT_RELATIVE_COLORIMETRIC,
    @@ -1034,6 +1085,18 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext     ContextID,
     
         cmsStageSampleCLut16bit(CLUT, BlackPreservingSampler, (void*) &bp, 0);
     
    +    // Insert possible devicelinks at the end
    +    for (i = lastProfilePos + 1; i < nProfiles; i++)
    +    {
    +        cmsPipeline* devlink = _cmsReadDevicelinkLUT(hProfiles[i], ICCIntents[i]);
    +        if (devlink == NULL)
    +            goto Cleanup;
    +
    +        if (!cmsPipelineCat(Result, devlink))
    +            goto Cleanup;
    +    }
    +
    +
     Cleanup:
     
         if (bp.cmyk2cmyk) cmsPipelineFree(bp.cmyk2cmyk);
    @@ -1046,6 +1109,8 @@ cmsPipeline* BlackPreservingKPlaneIntents(cmsContext     ContextID,
         return Result;
     }
     
    +
    +
     // Link routines ------------------------------------------------------------------------------------------------------
     
     // Chain several profiles into a single LUT. It just checks the parameters and then calls the handler
    diff --git a/src/java.desktop/share/native/liblcms/cmsgamma.c b/src/java.desktop/share/native/liblcms/cmsgamma.c
    index 4ccbf4d2a2b..f266f2e05a6 100644
    --- a/src/java.desktop/share/native/liblcms/cmsgamma.c
    +++ b/src/java.desktop/share/native/liblcms/cmsgamma.c
    @@ -88,11 +88,11 @@ static cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFl
     
     // The built-in list
     static _cmsParametricCurvesCollection DefaultCurves = {
    -    9,                                  // # of curve types
    -    { 1, 2, 3, 4, 5, 6, 7, 8, 108 },    // Parametric curve ID
    -    { 1, 3, 4, 5, 7, 4, 5, 5, 1 },      // Parameters by type
    -    DefaultEvalParametricFn,            // Evaluator
    -    NULL                                // Next in chain
    +    10,                                      // # of curve types
    +    { 1, 2, 3, 4, 5, 6, 7, 8, 108, 109 },    // Parametric curve ID
    +    { 1, 3, 4, 5, 7, 4, 5, 5,   1,   1 },    // Parameters by type
    +    DefaultEvalParametricFn,                 // Evaluator
    +    NULL                                     // Next in chain
     };
     
     // Duplicates the zone of memory used by the plug-in in the new context
    @@ -338,6 +338,32 @@ cmsToneCurve* AllocateToneCurveStruct(cmsContext ContextID, cmsUInt32Number nEnt
     }
     
     
    +// Generates a sigmoidal function with desired steepness.
    +cmsINLINE double sigmoid_base(double k, double t)
    +{
    +    return (1.0 / (1.0 + exp(-k * t))) - 0.5;
    +}
    +
    +cmsINLINE double inverted_sigmoid_base(double k, double t)
    +{
    +    return -log((1.0 / (t + 0.5)) - 1.0) / k;
    +}
    +
    +cmsINLINE double sigmoid_factory(double k, double t)
    +{
    +    double correction = 0.5 / sigmoid_base(k, 1);
    +
    +    return correction * sigmoid_base(k, 2.0 * t - 1.0) + 0.5;
    +}
    +
    +cmsINLINE double inverse_sigmoid_factory(double k, double t)
    +{
    +    double correction = 0.5 / sigmoid_base(k, 1);
    +
    +    return (inverted_sigmoid_base(k, (t - 0.5) / correction) + 1.0) / 2.0;
    +}
    +
    +
     // Parametric Fn using floating point
     static
     cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Number Params[], cmsFloat64Number R)
    @@ -669,6 +695,7 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
            }
            break;
     
    +
        // S-Shaped: (1 - (1-x)^1/g)^1/g
        case 108:
            if (fabs(Params[0]) < MATRIX_DET_TOLERANCE)
    @@ -686,6 +713,15 @@ cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Nu
             Val = 1 - pow(1 - pow(R, Params[0]), Params[0]);
             break;
     
    +    // Sigmoidals
    +    case 109:
    +        Val = sigmoid_factory(Params[0], R);
    +        break;
    +
    +    case -109:
    +        Val = inverse_sigmoid_factory(Params[0], R);
    +        break;
    +
         default:
             // Unsupported parametric curve. Should never reach here
             return 0;
    @@ -971,7 +1007,7 @@ cmsToneCurve* CMSEXPORT cmsJoinToneCurve(cmsContext ContextID,
         //Iterate
         for (i=0; i <  nResultingPoints; i++) {
     
    -        t = (cmsFloat32Number) i / (nResultingPoints-1);
    +        t = (cmsFloat32Number) i / (cmsFloat32Number)(nResultingPoints-1);
             x = cmsEvalToneCurveFloat(X,  t);
             Res[i] = cmsEvalToneCurveFloat(Yreversed, x);
         }
    @@ -1185,6 +1221,7 @@ cmsBool  CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda
         cmsBool SuccessStatus = TRUE;
         cmsFloat32Number *w, *y, *z;
         cmsUInt32Number i, nItems, Zeros, Poles;
    +    cmsBool notCheck = FALSE;
     
         if (Tab != NULL && Tab->InterpParams != NULL)
         {
    @@ -1212,6 +1249,12 @@ cmsBool  CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda
                             w[i + 1] = 1.0;
                         }
     
    +                    if (lambda < 0)
    +                    {
    +                        notCheck = TRUE;
    +                        lambda = -lambda;
    +                    }
    +
                         if (smooth2(ContextID, w, y, z, (cmsFloat32Number)lambda, (int)nItems))
                         {
                             // Do some reality - checking...
    @@ -1224,7 +1267,7 @@ cmsBool  CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda
                                 if (z[i] < z[i - 1])
                                 {
                                     cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Non-Monotonic.");
    -                                SuccessStatus = FALSE;
    +                                SuccessStatus = notCheck;
                                     break;
                                 }
                             }
    @@ -1232,13 +1275,13 @@ cmsBool  CMSEXPORT cmsSmoothToneCurve(cmsToneCurve* Tab, cmsFloat64Number lambda
                             if (SuccessStatus && Zeros > (nItems / 3))
                             {
                                 cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly zeros.");
    -                            SuccessStatus = FALSE;
    +                            SuccessStatus = notCheck;
                             }
     
                             if (SuccessStatus && Poles > (nItems / 3))
                             {
                                 cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Degenerated, mostly poles.");
    -                            SuccessStatus = FALSE;
    +                            SuccessStatus = notCheck;
                             }
     
                             if (SuccessStatus) // Seems ok
    diff --git a/src/java.desktop/share/native/liblcms/cmsintrp.c b/src/java.desktop/share/native/liblcms/cmsintrp.c
    index 435c87cc7a7..8f2d0130e82 100644
    --- a/src/java.desktop/share/native/liblcms/cmsintrp.c
    +++ b/src/java.desktop/share/native/liblcms/cmsintrp.c
    @@ -434,12 +434,13 @@ void BilinearInterp16(CMSREGISTER const cmsUInt16Number Input[],
                const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
                int        OutChan, TotalOut;
                cmsS15Fixed16Number    fx, fy;
    -  CMSREGISTER int        rx, ry;
    -           int        x0, y0;
    -  CMSREGISTER int        X0, X1, Y0, Y1;
    -           int        d00, d01, d10, d11,
    -                      dx0, dx1,
    -                      dxy;
    +           CMSREGISTER int        rx, ry;
    +           int                    x0, y0;
    +           CMSREGISTER int        X0, X1, Y0, Y1;
    +
    +           int                    d00, d01, d10, d11,
    +                                  dx0, dx1,
    +                                  dxy;
     
         TotalOut   = p -> nOutputs;
     
    @@ -495,11 +496,12 @@ void TrilinearInterpFloat(const cmsFloat32Number Input[],
         int        x0, y0, z0,
                    X0, Y0, Z0, X1, Y1, Z1;
         int        TotalOut, OutChan;
    +
         cmsFloat32Number      fx, fy, fz,
    -        d000, d001, d010, d011,
    -        d100, d101, d110, d111,
    -        dx00, dx01, dx10, dx11,
    -        dxy0, dxy1, dxyz;
    +                          d000, d001, d010, d011,
    +                          d100, d101, d110, d111,
    +                          dx00, dx01, dx10, dx11,
    +                          dxy0, dxy1, dxyz;
     
         TotalOut   = p -> nOutputs;
     
    @@ -565,13 +567,13 @@ void TrilinearInterp16(CMSREGISTER const cmsUInt16Number Input[],
                const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
                int        OutChan, TotalOut;
                cmsS15Fixed16Number    fx, fy, fz;
    -  CMSREGISTER int        rx, ry, rz;
    -           int        x0, y0, z0;
    -  CMSREGISTER int        X0, X1, Y0, Y1, Z0, Z1;
    -           int        d000, d001, d010, d011,
    -                      d100, d101, d110, d111,
    -                      dx00, dx01, dx10, dx11,
    -                      dxy0, dxy1, dxyz;
    +           CMSREGISTER int        rx, ry, rz;
    +           int                    x0, y0, z0;
    +           CMSREGISTER int        X0, X1, Y0, Y1, Z0, Z1;
    +           int                    d000, d001, d010, d011,
    +                                  d100, d101, d110, d111,
    +                                  dx00, dx01, dx10, dx11,
    +                                  dxy0, dxy1, dxyz;
     
         TotalOut   = p -> nOutputs;
     
    @@ -639,8 +641,8 @@ void TetrahedralInterpFloat(const cmsFloat32Number Input[],
     {
         const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
         cmsFloat32Number     px, py, pz;
    -    int        x0, y0, z0,
    -               X0, Y0, Z0, X1, Y1, Z1;
    +    int                  x0, y0, z0,
    +                         X0, Y0, Z0, X1, Y1, Z1;
         cmsFloat32Number     rx, ry, rz;
         cmsFloat32Number     c0, c1=0, c2=0, c3=0;
         int                  OutChan, TotalOut;
    @@ -730,9 +732,6 @@ void TetrahedralInterpFloat(const cmsFloat32Number Input[],
     
     #undef DENS
     
    -
    -
    -
     static CMS_NO_SANITIZE
     void TetrahedralInterp16(CMSREGISTER const cmsUInt16Number Input[],
                              CMSREGISTER cmsUInt16Number Output[],
    @@ -743,7 +742,7 @@ void TetrahedralInterp16(CMSREGISTER const cmsUInt16Number Input[],
         cmsS15Fixed16Number rx, ry, rz;
         int x0, y0, z0;
         cmsS15Fixed16Number c0, c1, c2, c3, Rest;
    -    cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
    +    cmsUInt32Number X0, X1, Y0, Y1, Z0, Z1;
         cmsUInt32Number TotalOut = p -> nOutputs;
     
         fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
    @@ -767,7 +766,7 @@ void TetrahedralInterp16(CMSREGISTER const cmsUInt16Number Input[],
         Z0 = p -> opta[0] * z0;
         Z1 = (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
     
    -    LutTable = &LutTable[X0+Y0+Z0];
    +    LutTable += X0+Y0+Z0;
     
         // Output should be computed as x = ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))
         // which expands as: x = (Rest + ((Rest+0x7fff)/0xFFFF) + 0x8000)>>16
    @@ -1051,8 +1050,6 @@ void Eval4Inputs(CMSREGISTER const cmsUInt16Number Input[],
     
     // For more that 3 inputs (i.e., CMYK)
     // evaluate two 3-dimensional interpolations and then linearly interpolate between them.
    -
    -
     static
     void Eval4InputsFloat(const cmsFloat32Number Input[],
                           cmsFloat32Number Output[],
    @@ -1095,351 +1092,102 @@ void Eval4InputsFloat(const cmsFloat32Number Input[],
            }
     }
     
    -
    -static CMS_NO_SANITIZE
    -void Eval5Inputs(CMSREGISTER const cmsUInt16Number Input[],
    -                 CMSREGISTER cmsUInt16Number Output[],
    -
    -                 CMSREGISTER const cmsInterpParams* p16)
    -{
    -       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
    -       cmsS15Fixed16Number fk;
    -       cmsS15Fixed16Number k0, rk;
    -       int K0, K1;
    -       const cmsUInt16Number* T;
    -       cmsUInt32Number i;
    -       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
    -       cmsInterpParams p1;
    -
    -
    -       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
    -       k0 = FIXED_TO_INT(fk);
    -       rk = FIXED_REST_TO_INT(fk);
    -
    -       K0 = p16 -> opta[4] * k0;
    -       K1 = p16 -> opta[4] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
    -
    -       p1 = *p16;
    -       memmove(&p1.Domain[0], &p16 ->Domain[1], 4*sizeof(cmsUInt32Number));
    -
    -       T = LutTable + K0;
    -       p1.Table = T;
    -
    -       Eval4Inputs(Input + 1, Tmp1, &p1);
    -
    -       T = LutTable + K1;
    -       p1.Table = T;
    -
    -       Eval4Inputs(Input + 1, Tmp2, &p1);
    -
    -       for (i=0; i < p16 -> nOutputs; i++) {
    -
    -              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
    -       }
    -
    -}
    -
    -
    -static
    -void Eval5InputsFloat(const cmsFloat32Number Input[],
    -                      cmsFloat32Number Output[],
    -                      const cmsInterpParams* p)
    -{
    -       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
    -       cmsFloat32Number rest;
    -       cmsFloat32Number pk;
    -       int k0, K0, K1;
    -       const cmsFloat32Number* T;
    -       cmsUInt32Number i;
    -       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
    -       cmsInterpParams p1;
    -
    -       pk = fclamp(Input[0]) * p->Domain[0];
    -       k0 = _cmsQuickFloor(pk);
    -       rest = pk - (cmsFloat32Number) k0;
    -
    -       K0 = p -> opta[4] * k0;
    -       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[4]);
    -
    -       p1 = *p;
    -       memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number));
    -
    -       T = LutTable + K0;
    -       p1.Table = T;
    -
    -       Eval4InputsFloat(Input + 1,  Tmp1, &p1);
    -
    -       T = LutTable + K1;
    -       p1.Table = T;
    -
    -       Eval4InputsFloat(Input + 1,  Tmp2, &p1);
    -
    -       for (i=0; i < p -> nOutputs; i++) {
    -
    -              cmsFloat32Number y0 = Tmp1[i];
    -              cmsFloat32Number y1 = Tmp2[i];
    -
    -              Output[i] = y0 + (y1 - y0) * rest;
    -       }
    -}
    -
    -
    -
    -static CMS_NO_SANITIZE
    -void Eval6Inputs(CMSREGISTER const cmsUInt16Number Input[],
    -                 CMSREGISTER cmsUInt16Number Output[],
    -                 CMSREGISTER const cmsInterpParams* p16)
    -{
    -       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
    -       cmsS15Fixed16Number fk;
    -       cmsS15Fixed16Number k0, rk;
    -       int K0, K1;
    -       const cmsUInt16Number* T;
    -       cmsUInt32Number i;
    -       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
    -       cmsInterpParams p1;
    -
    -       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
    -       k0 = FIXED_TO_INT(fk);
    -       rk = FIXED_REST_TO_INT(fk);
    -
    -       K0 = p16 -> opta[5] * k0;
    -       K1 = p16 -> opta[5] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
    -
    -       p1 = *p16;
    -       memmove(&p1.Domain[0], &p16 ->Domain[1], 5*sizeof(cmsUInt32Number));
    -
    -       T = LutTable + K0;
    -       p1.Table = T;
    -
    -       Eval5Inputs(Input + 1, Tmp1, &p1);
    -
    -       T = LutTable + K1;
    -       p1.Table = T;
    -
    -       Eval5Inputs(Input + 1, Tmp2, &p1);
    -
    -       for (i=0; i < p16 -> nOutputs; i++) {
    -
    -              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
    -       }
    -
    -}
    -
    -
    -static
    -void Eval6InputsFloat(const cmsFloat32Number Input[],
    -                      cmsFloat32Number Output[],
    -                      const cmsInterpParams* p)
    -{
    -       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
    -       cmsFloat32Number rest;
    -       cmsFloat32Number pk;
    -       int k0, K0, K1;
    -       const cmsFloat32Number* T;
    -       cmsUInt32Number i;
    -       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
    -       cmsInterpParams p1;
    -
    -       pk = fclamp(Input[0]) * p->Domain[0];
    -       k0 = _cmsQuickFloor(pk);
    -       rest = pk - (cmsFloat32Number) k0;
    -
    -       K0 = p -> opta[5] * k0;
    -       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[5]);
    -
    -       p1 = *p;
    -       memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number));
    -
    -       T = LutTable + K0;
    -       p1.Table = T;
    -
    -       Eval5InputsFloat(Input + 1,  Tmp1, &p1);
    -
    -       T = LutTable + K1;
    -       p1.Table = T;
    -
    -       Eval5InputsFloat(Input + 1,  Tmp2, &p1);
    -
    -       for (i=0; i < p -> nOutputs; i++) {
    -
    -              cmsFloat32Number y0 = Tmp1[i];
    -              cmsFloat32Number y1 = Tmp2[i];
    -
    -              Output[i] = y0 + (y1 - y0) * rest;
    -       }
    -}
    -
    -
    -static CMS_NO_SANITIZE
    -void Eval7Inputs(CMSREGISTER const cmsUInt16Number Input[],
    -                 CMSREGISTER cmsUInt16Number Output[],
    -                 CMSREGISTER const cmsInterpParams* p16)
    -{
    -       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
    -       cmsS15Fixed16Number fk;
    -       cmsS15Fixed16Number k0, rk;
    -       int K0, K1;
    -       const cmsUInt16Number* T;
    -       cmsUInt32Number i;
    -       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
    -       cmsInterpParams p1;
    -
    -
    -       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
    -       k0 = FIXED_TO_INT(fk);
    -       rk = FIXED_REST_TO_INT(fk);
    -
    -       K0 = p16 -> opta[6] * k0;
    -       K1 = p16 -> opta[6] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
    -
    -       p1 = *p16;
    -       memmove(&p1.Domain[0], &p16 ->Domain[1], 6*sizeof(cmsUInt32Number));
    -
    -       T = LutTable + K0;
    -       p1.Table = T;
    -
    -       Eval6Inputs(Input + 1, Tmp1, &p1);
    -
    -       T = LutTable + K1;
    -       p1.Table = T;
    -
    -       Eval6Inputs(Input + 1, Tmp2, &p1);
    -
    -       for (i=0; i < p16 -> nOutputs; i++) {
    -              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
    -       }
    -}
    -
    -
    -static
    -void Eval7InputsFloat(const cmsFloat32Number Input[],
    -                      cmsFloat32Number Output[],
    -                      const cmsInterpParams* p)
    -{
    -       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
    -       cmsFloat32Number rest;
    -       cmsFloat32Number pk;
    -       int k0, K0, K1;
    -       const cmsFloat32Number* T;
    -       cmsUInt32Number i;
    -       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
    -       cmsInterpParams p1;
    -
    -       pk = fclamp(Input[0]) * p->Domain[0];
    -       k0 = _cmsQuickFloor(pk);
    -       rest = pk - (cmsFloat32Number) k0;
    -
    -       K0 = p -> opta[6] * k0;
    -       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[6]);
    -
    -       p1 = *p;
    -       memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number));
    -
    -       T = LutTable + K0;
    -       p1.Table = T;
    -
    -       Eval6InputsFloat(Input + 1,  Tmp1, &p1);
    -
    -       T = LutTable + K1;
    -       p1.Table = T;
    -
    -       Eval6InputsFloat(Input + 1,  Tmp2, &p1);
    -
    -
    -       for (i=0; i < p -> nOutputs; i++) {
    -
    -              cmsFloat32Number y0 = Tmp1[i];
    -              cmsFloat32Number y1 = Tmp2[i];
    -
    -              Output[i] = y0 + (y1 - y0) * rest;
    -
    -       }
    -}
    -
    -static CMS_NO_SANITIZE
    -void Eval8Inputs(CMSREGISTER const cmsUInt16Number Input[],
    -                 CMSREGISTER cmsUInt16Number Output[],
    -                 CMSREGISTER const cmsInterpParams* p16)
    -{
    -       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
    -       cmsS15Fixed16Number fk;
    -       cmsS15Fixed16Number k0, rk;
    -       int K0, K1;
    -       const cmsUInt16Number* T;
    -       cmsUInt32Number i;
    -       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
    -       cmsInterpParams p1;
    -
    -       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
    -       k0 = FIXED_TO_INT(fk);
    -       rk = FIXED_REST_TO_INT(fk);
    -
    -       K0 = p16 -> opta[7] * k0;
    -       K1 = p16 -> opta[7] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
    -
    -       p1 = *p16;
    -       memmove(&p1.Domain[0], &p16 ->Domain[1], 7*sizeof(cmsUInt32Number));
    -
    -       T = LutTable + K0;
    -       p1.Table = T;
    -
    -       Eval7Inputs(Input + 1, Tmp1, &p1);
    -
    -       T = LutTable + K1;
    -       p1.Table = T;
    -       Eval7Inputs(Input + 1, Tmp2, &p1);
    -
    -       for (i=0; i < p16 -> nOutputs; i++) {
    -              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
    -       }
    +#define EVAL_FNS(N,NM) static CMS_NO_SANITIZE \
    +void Eval##N##Inputs(CMSREGISTER const cmsUInt16Number Input[], CMSREGISTER cmsUInt16Number Output[], CMSREGISTER const cmsInterpParams* p16)\
    +{\
    +       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;\
    +       cmsS15Fixed16Number fk;\
    +       cmsS15Fixed16Number k0, rk;\
    +       int K0, K1;\
    +       const cmsUInt16Number* T;\
    +       cmsUInt32Number i;\
    +       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
    +       cmsInterpParams p1;\
    +\
    +       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);\
    +       k0 = FIXED_TO_INT(fk);\
    +       rk = FIXED_REST_TO_INT(fk);\
    +\
    +       K0 = p16 -> opta[NM] * k0;\
    +       K1 = p16 -> opta[NM] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));\
    +\
    +       p1 = *p16;\
    +       memmove(&p1.Domain[0], &p16 ->Domain[1], NM*sizeof(cmsUInt32Number));\
    +\
    +       T = LutTable + K0;\
    +       p1.Table = T;\
    +\
    +       Eval##NM##Inputs(Input + 1, Tmp1, &p1);\
    +\
    +       T = LutTable + K1;\
    +       p1.Table = T;\
    +\
    +       Eval##NM##Inputs(Input + 1, Tmp2, &p1);\
    +\
    +       for (i=0; i < p16 -> nOutputs; i++) {\
    +\
    +              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);\
    +       }\
    +}\
    +\
    +static void Eval##N##InputsFloat(const cmsFloat32Number Input[], \
    +                                 cmsFloat32Number Output[],\
    +                                 const cmsInterpParams * p)\
    +{\
    +       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;\
    +       cmsFloat32Number rest;\
    +       cmsFloat32Number pk;\
    +       int k0, K0, K1;\
    +       const cmsFloat32Number* T;\
    +       cmsUInt32Number i;\
    +       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
    +       cmsInterpParams p1;\
    +\
    +       pk = fclamp(Input[0]) * p->Domain[0];\
    +       k0 = _cmsQuickFloor(pk);\
    +       rest = pk - (cmsFloat32Number) k0;\
    +\
    +       K0 = p -> opta[NM] * k0;\
    +       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[NM]);\
    +\
    +       p1 = *p;\
    +       memmove(&p1.Domain[0], &p ->Domain[1], NM*sizeof(cmsUInt32Number));\
    +\
    +       T = LutTable + K0;\
    +       p1.Table = T;\
    +\
    +       Eval##NM##InputsFloat(Input + 1, Tmp1, &p1);\
    +\
    +       T = LutTable + K1;\
    +       p1.Table = T;\
    +\
    +       Eval##NM##InputsFloat(Input + 1, Tmp2, &p1);\
    +\
    +       for (i=0; i < p -> nOutputs; i++) {\
    +\
    +              cmsFloat32Number y0 = Tmp1[i];\
    +              cmsFloat32Number y1 = Tmp2[i];\
    +\
    +              Output[i] = y0 + (y1 - y0) * rest;\
    +       }\
     }
     
     
    +/**
    +* Thanks to Carles Llopis for the templating idea
    +*/
    +EVAL_FNS(5, 4)
    +EVAL_FNS(6, 5)
    +EVAL_FNS(7, 6)
    +EVAL_FNS(8, 7)
    +EVAL_FNS(9, 8)
    +EVAL_FNS(10, 9)
    +EVAL_FNS(11, 10)
    +EVAL_FNS(12, 11)
    +EVAL_FNS(13, 12)
    +EVAL_FNS(14, 13)
    +EVAL_FNS(15, 14)
     
    -static
    -void Eval8InputsFloat(const cmsFloat32Number Input[],
    -                      cmsFloat32Number Output[],
    -                      const cmsInterpParams* p)
    -{
    -       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
    -       cmsFloat32Number rest;
    -       cmsFloat32Number pk;
    -       int k0, K0, K1;
    -       const cmsFloat32Number* T;
    -       cmsUInt32Number i;
    -       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
    -       cmsInterpParams p1;
    -
    -       pk = fclamp(Input[0]) * p->Domain[0];
    -       k0 = _cmsQuickFloor(pk);
    -       rest = pk - (cmsFloat32Number) k0;
    -
    -       K0 = p -> opta[7] * k0;
    -       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[7]);
    -
    -       p1 = *p;
    -       memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number));
    -
    -       T = LutTable + K0;
    -       p1.Table = T;
    -
    -       Eval7InputsFloat(Input + 1,  Tmp1, &p1);
    -
    -       T = LutTable + K1;
    -       p1.Table = T;
    -
    -       Eval7InputsFloat(Input + 1,  Tmp2, &p1);
    -
    -
    -       for (i=0; i < p -> nOutputs; i++) {
    -
    -              cmsFloat32Number y0 = Tmp1[i];
    -              cmsFloat32Number y1 = Tmp2[i];
    -
    -              Output[i] = y0 + (y1 - y0) * rest;
    -       }
    -}
     
     // The default factory
     static
    @@ -1540,6 +1288,53 @@ cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cm
                        Interpolation.Lerp16    =  Eval8Inputs;
                    break;
     
    +           case 9:
    +               if (IsFloat)
    +                   Interpolation.LerpFloat = Eval9InputsFloat;
    +               else
    +                   Interpolation.Lerp16 = Eval9Inputs;
    +               break;
    +
    +           case 10:
    +               if (IsFloat)
    +                   Interpolation.LerpFloat = Eval10InputsFloat;
    +               else
    +                   Interpolation.Lerp16 = Eval10Inputs;
    +               break;
    +
    +           case 11:
    +               if (IsFloat)
    +                   Interpolation.LerpFloat = Eval11InputsFloat;
    +               else
    +                   Interpolation.Lerp16 = Eval11Inputs;
    +               break;
    +
    +           case 12:
    +               if (IsFloat)
    +                   Interpolation.LerpFloat = Eval12InputsFloat;
    +               else
    +                   Interpolation.Lerp16 = Eval12Inputs;
    +               break;
    +
    +           case 13:
    +               if (IsFloat)
    +                   Interpolation.LerpFloat = Eval13InputsFloat;
    +               else
    +                   Interpolation.Lerp16 = Eval13Inputs;
    +               break;
    +
    +           case 14:
    +               if (IsFloat)
    +                   Interpolation.LerpFloat = Eval14InputsFloat;
    +               else
    +                   Interpolation.Lerp16 = Eval14Inputs;
    +               break;
    +
    +           case 15:
    +               if (IsFloat)
    +                   Interpolation.LerpFloat = Eval15InputsFloat;
    +               else
    +                   Interpolation.Lerp16 = Eval15Inputs;
                    break;
     
                default:
    diff --git a/src/java.desktop/share/native/liblcms/cmsio0.c b/src/java.desktop/share/native/liblcms/cmsio0.c
    index 6c219722ae7..70be6a6ad14 100644
    --- a/src/java.desktop/share/native/liblcms/cmsio0.c
    +++ b/src/java.desktop/share/native/liblcms/cmsio0.c
    @@ -290,7 +290,7 @@ cmsIOHANDLER* CMSEXPORT cmsOpenIOhandlerFromMem(cmsContext ContextID, void *Buff
     
                 _cmsFree(ContextID, fm);
                 _cmsFree(ContextID, iohandler);
    -            cmsSignalError(ContextID, cmsERROR_READ, "Couldn't allocate %ld bytes for profile", size);
    +            cmsSignalError(ContextID, cmsERROR_READ, "Couldn't allocate %ld bytes for profile", (long) size);
                 return NULL;
             }
     
    @@ -1232,25 +1232,28 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig)
                 // In this case a blind copy of the block data is performed
                 if (FileOrig != NULL && Icc -> TagOffsets[i]) {
     
    -                cmsUInt32Number TagSize   = FileOrig -> TagSizes[i];
    -                cmsUInt32Number TagOffset = FileOrig -> TagOffsets[i];
    -                void* Mem;
    +                if (FileOrig->IOhandler != NULL)
    +                {
    +                    cmsUInt32Number TagSize = FileOrig->TagSizes[i];
    +                    cmsUInt32Number TagOffset = FileOrig->TagOffsets[i];
    +                    void* Mem;
     
    -                if (!FileOrig ->IOhandler->Seek(FileOrig ->IOhandler, TagOffset)) return FALSE;
    +                    if (!FileOrig->IOhandler->Seek(FileOrig->IOhandler, TagOffset)) return FALSE;
     
    -                Mem = _cmsMalloc(Icc ->ContextID, TagSize);
    -                if (Mem == NULL) return FALSE;
    +                    Mem = _cmsMalloc(Icc->ContextID, TagSize);
    +                    if (Mem == NULL) return FALSE;
     
    -                if (FileOrig ->IOhandler->Read(FileOrig->IOhandler, Mem, TagSize, 1) != 1) return FALSE;
    -                if (!io ->Write(io, TagSize, Mem)) return FALSE;
    -                _cmsFree(Icc ->ContextID, Mem);
    +                    if (FileOrig->IOhandler->Read(FileOrig->IOhandler, Mem, TagSize, 1) != 1) return FALSE;
    +                    if (!io->Write(io, TagSize, Mem)) return FALSE;
    +                    _cmsFree(Icc->ContextID, Mem);
     
    -                Icc -> TagSizes[i] = (io ->UsedSpace - Begin);
    +                    Icc->TagSizes[i] = (io->UsedSpace - Begin);
     
     
    -                // Align to 32 bit boundary.
    -                if (! _cmsWriteAlignment(io))
    -                    return FALSE;
    +                    // Align to 32 bit boundary.
    +                    if (!_cmsWriteAlignment(io))
    +                        return FALSE;
    +                }
                 }
     
                 continue;
    diff --git a/src/java.desktop/share/native/liblcms/cmslut.c b/src/java.desktop/share/native/liblcms/cmslut.c
    index f20e185c44a..6eb803fe558 100644
    --- a/src/java.desktop/share/native/liblcms/cmslut.c
    +++ b/src/java.desktop/share/native/liblcms/cmslut.c
    @@ -1366,7 +1366,7 @@ void _LUTeval16(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Num
     
     // Does evaluate the LUT on cmsFloat32Number-basis.
     static
    -void _LUTevalFloat(CMSREGISTER const cmsFloat32Number In[], CMSREGISTER cmsFloat32Number Out[], const void* D)
    +void _LUTevalFloat(const cmsFloat32Number In[], cmsFloat32Number Out[], const void* D)
     {
         cmsPipeline* lut = (cmsPipeline*) D;
         cmsStage *mpe;
    @@ -1687,7 +1687,7 @@ cmsUInt32Number CMSEXPORT cmsPipelineStageCount(const cmsPipeline* lut)
     // This function may be used to set the optional evaluator and a block of private data. If private data is being used, an optional
     // duplicator and free functions should also be specified in order to duplicate the LUT construct. Use NULL to inhibit such functionality.
     void CMSEXPORT _cmsPipelineSetOptimizationParameters(cmsPipeline* Lut,
    -                                        _cmsOPTeval16Fn Eval16,
    +                                        _cmsPipelineEval16Fn Eval16,
                                             void* PrivateData,
                                             _cmsFreeUserDataFn FreePrivateDataFn,
                                             _cmsDupUserDataFn  DupPrivateDataFn)
    diff --git a/src/java.desktop/share/native/liblcms/cmsnamed.c b/src/java.desktop/share/native/liblcms/cmsnamed.c
    index 9ab2ea1796a..95a3b5ef8e1 100644
    --- a/src/java.desktop/share/native/liblcms/cmsnamed.c
    +++ b/src/java.desktop/share/native/liblcms/cmsnamed.c
    @@ -209,12 +209,16 @@ cmsBool AddMLUBlock(cmsMLU* mlu, cmsUInt32Number size, const wchar_t *Block,
     
     // Convert from a 3-char code to a cmsUInt16Number. It is done in this way because some
     // compilers don't properly align beginning of strings
    -
     static
     cmsUInt16Number strTo16(const char str[3])
     {
    -    const cmsUInt8Number* ptr8 = (const cmsUInt8Number*)str;
    -    cmsUInt16Number n = (cmsUInt16Number)(((cmsUInt16Number)ptr8[0] << 8) | ptr8[1]);
    +    const cmsUInt8Number* ptr8;
    +    cmsUInt16Number n;
    +
    +    // For non-existent strings
    +    if (str == NULL) return 0;
    +    ptr8 = (const cmsUInt8Number*)str;
    +    n = (cmsUInt16Number)(((cmsUInt16Number)ptr8[0] << 8) | ptr8[1]);
     
         return n;
     }
    @@ -229,6 +233,7 @@ void strFrom16(char str[3], cmsUInt16Number n)
     }
     
     // Add an ASCII entry. Do not add any \0 termination (ICC1v43_2010-12.pdf page 61)
    +// In the case the user explicitely sets an empty string, we force a \0
     cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const char CountryCode[3], const char* ASCIIString)
     {
         cmsUInt32Number i, len = (cmsUInt32Number) strlen(ASCIIString);
    @@ -239,6 +244,12 @@ cmsBool CMSEXPORT cmsMLUsetASCII(cmsMLU* mlu, const char LanguageCode[3], const
     
         if (mlu == NULL) return FALSE;
     
    +    // len == 0 would prevent operation, so we set a empty string pointing to zero
    +    if (len == 0)
    +    {
    +        len = 1;
    +    }
    +
         WStr = (wchar_t*) _cmsCalloc(mlu ->ContextID, len,  sizeof(wchar_t));
         if (WStr == NULL) return FALSE;
     
    @@ -276,6 +287,9 @@ cmsBool  CMSEXPORT cmsMLUsetWide(cmsMLU* mlu, const char Language[3], const char
         if (WideString == NULL) return FALSE;
     
         len = (cmsUInt32Number) (mywcslen(WideString)) * sizeof(wchar_t);
    +    if (len == 0)
    +        len = sizeof(wchar_t);
    +
         return AddMLUBlock(mlu, len, WideString, Lang, Cntry);
     }
     
    diff --git a/src/java.desktop/share/native/liblcms/cmsopt.c b/src/java.desktop/share/native/liblcms/cmsopt.c
    index 5b4b1ea6a64..e83b2e0be6d 100644
    --- a/src/java.desktop/share/native/liblcms/cmsopt.c
    +++ b/src/java.desktop/share/native/liblcms/cmsopt.c
    @@ -408,7 +408,20 @@ Prelin16Data* PrelinOpt16alloc(cmsContext ContextID,
     
     
         p16 -> EvalCurveOut16 = (_cmsInterpFn16*) _cmsCalloc(ContextID, nOutputs, sizeof(_cmsInterpFn16));
    +    if (p16->EvalCurveOut16 == NULL)
    +    {
    +        _cmsFree(ContextID, p16);
    +        return NULL;
    +    }
    +
         p16 -> ParamsCurveOut16 = (cmsInterpParams**) _cmsCalloc(ContextID, nOutputs, sizeof(cmsInterpParams* ));
    +    if (p16->ParamsCurveOut16 == NULL)
    +    {
    +
    +        _cmsFree(ContextID, p16->EvalCurveOut16);
    +        _cmsFree(ContextID, p16);
    +        return NULL;
    +    }
     
         for (i=0; i < nOutputs; i++) {
     
    @@ -435,7 +448,9 @@ Prelin16Data* PrelinOpt16alloc(cmsContext ContextID,
     // Sampler implemented by another LUT. This is a clean way to precalculate the devicelink 3D CLUT for
     // almost any transform. We use floating point precision and then convert from floating point to 16 bits.
     static
    -cmsInt32Number XFormSampler16(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Number Out[], CMSREGISTER void* Cargo)
    +cmsInt32Number XFormSampler16(CMSREGISTER const cmsUInt16Number In[],
    +                              CMSREGISTER cmsUInt16Number Out[],
    +                              CMSREGISTER void* Cargo)
     {
         cmsPipeline* Lut = (cmsPipeline*) Cargo;
         cmsFloat32Number InFloat[cmsMAXCHANNELS], OutFloat[cmsMAXCHANNELS];
    @@ -794,7 +809,7 @@ cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt3
     
         if (DataSetIn == NULL && DataSetOut == NULL) {
     
    -        _cmsPipelineSetOptimizationParameters(Dest, (_cmsOPTeval16Fn) DataCLUT->Params->Interpolation.Lerp16, DataCLUT->Params, NULL, NULL);
    +        _cmsPipelineSetOptimizationParameters(Dest, (_cmsPipelineEval16Fn) DataCLUT->Params->Interpolation.Lerp16, DataCLUT->Params, NULL, NULL);
         }
         else {
     
    @@ -939,8 +954,8 @@ void* Prelin8dup(cmsContext ContextID, const void* ptr)
     #define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
     static CMS_NO_SANITIZE
     void PrelinEval8(CMSREGISTER const cmsUInt16Number Input[],
    -                  CMSREGISTER cmsUInt16Number Output[],
    -                  CMSREGISTER const void* D)
    +                 CMSREGISTER cmsUInt16Number Output[],
    +                 CMSREGISTER const void* D)
     {
     
         cmsUInt8Number         r, g, b;
    @@ -957,9 +972,9 @@ void PrelinEval8(CMSREGISTER const cmsUInt16Number Input[],
         g = (cmsUInt8Number) (Input[1] >> 8);
         b = (cmsUInt8Number) (Input[2] >> 8);
     
    -    X0 = X1 = (cmsS15Fixed16Number) p8->X0[r];
    -    Y0 = Y1 = (cmsS15Fixed16Number) p8->Y0[g];
    -    Z0 = Z1 = (cmsS15Fixed16Number) p8->Z0[b];
    +    X0 = (cmsS15Fixed16Number) p8->X0[r];
    +    Y0 = (cmsS15Fixed16Number) p8->Y0[g];
    +    Z0 = (cmsS15Fixed16Number) p8->Z0[b];
     
         rx = p8 ->rx[r];
         ry = p8 ->ry[g];
    @@ -1361,8 +1376,8 @@ Curves16Data* CurvesAlloc(cmsContext ContextID, cmsUInt32Number nCurves, cmsUInt
     
     static
     void FastEvaluateCurves8(CMSREGISTER const cmsUInt16Number In[],
    -                          CMSREGISTER cmsUInt16Number Out[],
    -                          CMSREGISTER const void* D)
    +                         CMSREGISTER cmsUInt16Number Out[],
    +                         CMSREGISTER const void* D)
     {
         Curves16Data* Data = (Curves16Data*) D;
         int x;
    @@ -1922,7 +1937,7 @@ cmsBool  _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Dat
     }
     
     // The entry point for LUT optimization
    -cmsBool _cmsOptimizePipeline(cmsContext ContextID,
    +cmsBool CMSEXPORT _cmsOptimizePipeline(cmsContext ContextID,
                                  cmsPipeline**    PtrLut,
                                  cmsUInt32Number  Intent,
                                  cmsUInt32Number* InputFormat,
    diff --git a/src/java.desktop/share/native/liblcms/cmspack.c b/src/java.desktop/share/native/liblcms/cmspack.c
    index ca0d2877c3e..0ec3edab5d5 100644
    --- a/src/java.desktop/share/native/liblcms/cmspack.c
    +++ b/src/java.desktop/share/native/liblcms/cmspack.c
    @@ -2836,7 +2836,7 @@ cmsUInt8Number* UnrollHalfTo16(CMSREGISTER _cmsTRANSFORM* info,
     
             if (Reverse) v = maximum - v;
     
    -        wIn[index] = _cmsQuickSaturateWord(v * maximum);
    +        wIn[index] = _cmsQuickSaturateWord((cmsFloat64Number) v * maximum);
         }
     
     
    diff --git a/src/java.desktop/share/native/liblcms/cmspcs.c b/src/java.desktop/share/native/liblcms/cmspcs.c
    index 31744a6c973..6c628ed5e46 100644
    --- a/src/java.desktop/share/native/liblcms/cmspcs.c
    +++ b/src/java.desktop/share/native/liblcms/cmspcs.c
    @@ -685,7 +685,7 @@ cmsFloat64Number CMSEXPORT cmsCIE2000DeltaE(const cmsCIELab* Lab1, const cmsCIEL
     
     // This function returns a number of gridpoints to be used as LUT table. It assumes same number
     // of gripdpoints in all dimensions. Flags may override the choice.
    -cmsUInt32Number _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags)
    +cmsUInt32Number CMSEXPORT _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags)
     {
         cmsUInt32Number nChannels;
     
    diff --git a/src/java.desktop/share/native/liblcms/cmsplugin.c b/src/java.desktop/share/native/liblcms/cmsplugin.c
    index bff4adc25a9..037e6cbcdf1 100644
    --- a/src/java.desktop/share/native/liblcms/cmsplugin.c
    +++ b/src/java.desktop/share/native/liblcms/cmsplugin.c
    @@ -527,6 +527,7 @@ cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...)
         int len;
         cmsUInt8Number Buffer[2048];
         cmsBool rc;
    +    cmsUInt8Number* ptr;
     
         _cmsAssert(io != NULL);
         _cmsAssert(frm != NULL);
    @@ -539,6 +540,13 @@ cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...)
             return FALSE;   // Truncated, which is a fatal error for us
         }
     
    +    // setlocale may be active, no commas are needed in PS generator
    +    // and PS generator is our only client
    +    for (ptr = Buffer; *ptr; ptr++)
    +    {
    +        if (*ptr == ',') *ptr = '.';
    +    }
    +
         rc = io ->Write(io, (cmsUInt32Number) len, Buffer);
     
         va_end(args);
    diff --git a/src/java.desktop/share/native/liblcms/cmsps2.c b/src/java.desktop/share/native/liblcms/cmsps2.c
    index d02d6b55a3b..e5274540064 100644
    --- a/src/java.desktop/share/native/liblcms/cmsps2.c
    +++ b/src/java.desktop/share/native/liblcms/cmsps2.c
    @@ -558,9 +558,10 @@ void Emit1Gamma(cmsIOHANDLER* m, cmsToneCurve* Table, const char* name)
     // Compare gamma table
     
     static
    -cmsBool GammaTableEquals(cmsUInt16Number* g1, cmsUInt16Number* g2, cmsUInt32Number nEntries)
    +cmsBool GammaTableEquals(cmsUInt16Number* g1, cmsUInt16Number* g2, cmsUInt32Number nG1, cmsUInt32Number nG2)
     {
    -    return memcmp(g1, g2, nEntries* sizeof(cmsUInt16Number)) == 0;
    +    if (nG1 != nG2) return FALSE;
    +    return memcmp(g1, g2, nG1 * sizeof(cmsUInt16Number)) == 0;
     }
     
     
    @@ -576,12 +577,12 @@ void EmitNGamma(cmsIOHANDLER* m, cmsUInt32Number n, cmsToneCurve* g[], const cha
         {
             if (g[i] == NULL) return; // Error
     
    -        if (i > 0 && GammaTableEquals(g[i-1]->Table16, g[i]->Table16, g[i]->nEntries)) {
    +        if (i > 0 && GammaTableEquals(g[i-1]->Table16, g[i]->Table16, g[i-1]->nEntries, g[i]->nEntries)) {
     
                 _cmsIOPrintf(m, "/%s%d /%s%d load def\n", nameprefix, i, nameprefix, i-1);
             }
             else {
    -            snprintf(buffer, sizeof(buffer), "%s%d", nameprefix, i);
    +            snprintf(buffer, sizeof(buffer), "%s%d", nameprefix, (int) i);
                 buffer[sizeof(buffer)-1] = '\0';
                 Emit1Gamma(m, g[i], buffer);
             }
    @@ -836,7 +837,7 @@ int EmitCIEBasedDEF(cmsIOHANDLER* m, cmsPipeline* Pipeline, cmsUInt32Number Inte
     
         if (cmsStageType(mpe) == cmsSigCurveSetElemType) {
     
    -        numchans = cmsStageOutputChannels(mpe);
    +        numchans = (int) cmsStageOutputChannels(mpe);
             for (i = 0; i < numchans; ++i) {
                 snprintf(buffer, sizeof(buffer), "lcms2gammaproc%d", i);
                 buffer[sizeof(buffer) - 1] = '\0';
    diff --git a/src/java.desktop/share/native/liblcms/cmssamp.c b/src/java.desktop/share/native/liblcms/cmssamp.c
    index 5609eab8d4b..d3836420b3f 100644
    --- a/src/java.desktop/share/native/liblcms/cmssamp.c
    +++ b/src/java.desktop/share/native/liblcms/cmssamp.c
    @@ -112,10 +112,10 @@ cmsBool  BlackPointAsDarkerColorant(cmsHPROFILE    hInput,
             return FALSE;
         }
     
    -    // Create a formatter which has n channels and floating point
    +    // Create a formatter which has n channels and no floating point
         dwFormat = cmsFormatterForColorspaceOfProfile(hInput, 2, FALSE);
     
    -   // Try to get black by using black colorant
    +    // Try to get black by using black colorant
         Space = cmsGetColorSpace(hInput);
     
         // This function returns darker colorant in 16 bits for several spaces
    diff --git a/src/java.desktop/share/native/liblcms/cmstypes.c b/src/java.desktop/share/native/liblcms/cmstypes.c
    index fc667b9a9b4..006f98b084d 100644
    --- a/src/java.desktop/share/native/liblcms/cmstypes.c
    +++ b/src/java.desktop/share/native/liblcms/cmstypes.c
    @@ -1895,6 +1895,7 @@ cmsBool  Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
         mpe = NewLUT -> Elements;
         if (mpe ->Type == cmsSigMatrixElemType) {
     
    +        if (mpe->InputChannels != 3 || mpe->OutputChannels != 3) return FALSE;
             MatMPE = (_cmsStageMatrixData*) mpe ->Data;
             mpe = mpe -> Next;
         }
    @@ -1920,7 +1921,6 @@ cmsBool  Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
             return FALSE;
         }
     
    -
         if (clut == NULL)
             clutPoints = 0;
         else
    @@ -1935,15 +1935,13 @@ cmsBool  Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,
     
         if (MatMPE != NULL) {
     
    -                for (i = 0; i < n; i++)
    +                for (i = 0; i < 9; i++)
                     {
                             if (!_cmsWrite15Fixed16Number(io, MatMPE->Double[i])) return FALSE;
                     }
         }
         else {
     
    -                if (n != 9) return FALSE;
    -
             if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
             if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
             if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
    @@ -3029,6 +3027,9 @@ void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER
         }
     
         List = cmsAllocNamedColorList(self ->ContextID, Count, 0, "", "");
    +    if (List == NULL)
    +        return NULL;
    +
         for (i=0; i < Count; i++) {
     
             if (io ->Read(io, Name, 32, 1) != 1) goto Error;
    diff --git a/src/java.desktop/share/native/liblcms/cmsxform.c b/src/java.desktop/share/native/liblcms/cmsxform.c
    index 162e69e4bc3..6a2170c8fd2 100644
    --- a/src/java.desktop/share/native/liblcms/cmsxform.c
    +++ b/src/java.desktop/share/native/liblcms/cmsxform.c
    @@ -302,7 +302,7 @@ void FloatXFORM(_cmsTRANSFORM* p,
         strideIn = 0;
         strideOut = 0;
         memset(fIn, 0, sizeof(fIn));
    -    memset(fOut, 0, sizeof(fIn));
    +    memset(fOut, 0, sizeof(fOut));
     
         for (i = 0; i < LineCount; i++) {
     
    @@ -476,7 +476,7 @@ void TransformOnePixelWithGamutCheck(_cmsTRANSFORM* p,
         p ->GamutCheck ->Eval16Fn(wIn, &wOutOfGamut, p ->GamutCheck ->Data);
         if (wOutOfGamut >= 1) {
     
    -        cmsUInt16Number i;
    +        cmsUInt32Number i;
             _cmsAlarmCodesChunkType* ContextAlarmCodes = (_cmsAlarmCodesChunkType*) _cmsContextGetClientChunk(p->ContextID, AlarmCodesContext);
     
             for (i=0; i < p ->Lut->OutputChannels; i++) {
    @@ -803,6 +803,12 @@ void CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMc
          if (ToOutput)  *ToOutput  = CMMcargo ->ToOutputFloat;
     }
     
    +// returns original flags
    +cmsUInt32Number CMSEXPORT _cmsGetTransformFlags(struct _cmstransform_struct* CMMcargo)
    +{
    +    _cmsAssert(CMMcargo != NULL);
    +    return CMMcargo->dwOriginalFlags;
    +}
     
     // Allocate transform struct and set it to defaults. Ask the optimization plug-in about if those formats are proper
     // for separated transforms. If this is the case,
    diff --git a/src/java.desktop/share/native/liblcms/lcms2.h b/src/java.desktop/share/native/liblcms/lcms2.h
    index 8d5373919bb..69ada9ede64 100644
    --- a/src/java.desktop/share/native/liblcms/lcms2.h
    +++ b/src/java.desktop/share/native/liblcms/lcms2.h
    @@ -30,7 +30,7 @@
     //---------------------------------------------------------------------------------
     //
     //  Little Color Management System
    -//  Copyright (c) 1998-2020 Marti Maria Saguer
    +//  Copyright (c) 1998-2021 Marti Maria Saguer
     //
     // Permission is hereby granted, free of charge, to any person obtaining
     // a copy of this software and associated documentation files (the "Software"),
    @@ -52,7 +52,7 @@
     //
     //---------------------------------------------------------------------------------
     //
    -// Version 2.11
    +// Version 2.12
     //
     
     #ifndef _lcms2_H
    @@ -110,7 +110,7 @@ extern "C" {
     #endif
     
     // Version/release
    -#define LCMS_VERSION        2100
    +#define LCMS_VERSION        2120
     
     // I will give the chance of redefining basic types for compilers that are not fully C99 compliant
     #ifndef CMS_BASIC_TYPES_ALREADY_DEFINED
    @@ -1299,7 +1299,7 @@ typedef cmsInt32Number (* cmsSAMPLERFLOAT)(CMSREGISTER const cmsFloat32Number In
     #define SAMPLER_INSPECT     0x01000000
     
     // For CLUT only
    -CMSAPI cmsBool           CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe,    cmsSAMPLER16 Sampler, void* Cargo, cmsUInt32Number dwFlags);
    +CMSAPI cmsBool           CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, void* Cargo, cmsUInt32Number dwFlags);
     CMSAPI cmsBool           CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler, void* Cargo, cmsUInt32Number dwFlags);
     
     // Slicers
    diff --git a/src/java.desktop/share/native/liblcms/lcms2_internal.h b/src/java.desktop/share/native/liblcms/lcms2_internal.h
    index e1698f27ba2..d1c78208b82 100644
    --- a/src/java.desktop/share/native/liblcms/lcms2_internal.h
    +++ b/src/java.desktop/share/native/liblcms/lcms2_internal.h
    @@ -27,7 +27,7 @@
     // However, the following notice accompanied the original version of this
     // file:
     //
    -//---------------------------------------------------------------------------------
    +
     //
     //  Little Color Management System
     //  Copyright (c) 1998-2020 Marti Maria Saguer
    @@ -937,13 +937,7 @@ cmsStage*                          _cmsStageClipNegatives(cmsContext ContextID,
     
     
     // For curve set only
    -cmsToneCurve**     _cmsStageGetPtrToCurveSet(const cmsStage* mpe);
    -
    -
    -// Pipeline Evaluator (in floating point)
    -typedef void (* _cmsPipelineEvalFloatFn)(const cmsFloat32Number In[],
    -                                         cmsFloat32Number Out[],
    -                                         const void* Data);
    +cmsToneCurve**  _cmsStageGetPtrToCurveSet(const cmsStage* mpe);
     
     struct _cmsPipeline_struct {
     
    @@ -953,7 +947,7 @@ struct _cmsPipeline_struct {
         // Data & evaluators
         void *Data;
     
    -   _cmsOPTeval16Fn         Eval16Fn;
    +   _cmsPipelineEval16Fn    Eval16Fn;
        _cmsPipelineEvalFloatFn EvalFloatFn;
        _cmsFreeUserDataFn      FreeDataFn;
        _cmsDupUserDataFn       DupDataFn;
    @@ -1000,14 +994,14 @@ cmsSEQ* _cmsCompileProfileSequence(cmsContext ContextID, cmsUInt32Number nProfil
     
     CMSCHECKPOINT cmsUInt16Number  CMSEXPORT _cmsQuantizeVal(cmsFloat64Number i, cmsUInt32Number MaxSamples);
     
    -cmsUInt32Number  _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags);
    +CMSAPI cmsUInt32Number  CMSEXPORT _cmsReasonableGridpointsByColorspace(cmsColorSpaceSignature Colorspace, cmsUInt32Number dwFlags);
     
     cmsBool          _cmsEndPointsBySpace(cmsColorSpaceSignature Space,
                                           cmsUInt16Number **White,
                                           cmsUInt16Number **Black,
                                           cmsUInt32Number *nOutputs);
     
    -cmsBool          _cmsOptimizePipeline(cmsContext ContextID,
    +CMSAPI cmsBool CMSEXPORT _cmsOptimizePipeline(cmsContext ContextID,
                                           cmsPipeline**    Lut,
                                           cmsUInt32Number  Intent,
                                           cmsUInt32Number* InputFormat,
    diff --git a/src/java.desktop/share/native/liblcms/lcms2_plugin.h b/src/java.desktop/share/native/liblcms/lcms2_plugin.h
    index 7818e86eb6a..61e963ff5f8 100644
    --- a/src/java.desktop/share/native/liblcms/lcms2_plugin.h
    +++ b/src/java.desktop/share/native/liblcms/lcms2_plugin.h
    @@ -315,7 +315,7 @@ typedef union {
     #define CMS_LERP_FLAGS_TRILINEAR          0x0100        // Hint only
     
     
    -#define MAX_INPUT_DIMENSIONS 8
    +#define MAX_INPUT_DIMENSIONS 15
     
     typedef struct _cms_interp_struc {  // Used on all interpolations. Supplied by lcms2 when calling the interpolation function
     
    @@ -576,22 +576,28 @@ typedef struct {
     // the optimization  search. Or FALSE if it is unable to optimize and want to give a chance
     // to the rest of optimizers.
     
    -typedef void     (* _cmsOPTeval16Fn)(CMSREGISTER const cmsUInt16Number In[],
    -                                     CMSREGISTER cmsUInt16Number Out[],
    -                                     CMSREGISTER const void* Data);
    -
    -
     typedef cmsBool  (* _cmsOPToptimizeFn)(cmsPipeline** Lut,
                                            cmsUInt32Number  Intent,
                                            cmsUInt32Number* InputFormat,
                                            cmsUInt32Number* OutputFormat,
                                            cmsUInt32Number* dwFlags);
     
    +// Pipeline Evaluator (in 16 bits)
    +typedef void (* _cmsPipelineEval16Fn)(CMSREGISTER const cmsUInt16Number In[],
    +                                     CMSREGISTER cmsUInt16Number Out[],
    +                                     const void* Data);
    +
    +// Pipeline Evaluator (in floating point)
    +typedef void (* _cmsPipelineEvalFloatFn)(const cmsFloat32Number In[],
    +                                         cmsFloat32Number Out[],
    +                                         const void* Data);
    +
    +
     // This function may be used to set the optional evaluator and a block of private data. If private data is being used, an optional
     // duplicator and free functions should also be specified in order to duplicate the LUT construct. Use NULL to inhibit such functionality.
     
     CMSAPI void CMSEXPORT _cmsPipelineSetOptimizationParameters(cmsPipeline* Lut,
    -                                               _cmsOPTeval16Fn Eval16,
    +                                               _cmsPipelineEval16Fn Eval16,
                                                    void* PrivateData,
                                                    _cmsFreeUserDataFn FreePrivateDataFn,
                                                    _cmsDupUserDataFn DupPrivateDataFn);
    @@ -655,6 +661,9 @@ CMSAPI void * CMSEXPORT _cmsGetTransformUserData(struct _cmstransform_struct *CM
     CMSAPI void   CMSEXPORT _cmsGetTransformFormatters16   (struct _cmstransform_struct *CMMcargo, cmsFormatter16* FromInput, cmsFormatter16* ToOutput);
     CMSAPI void   CMSEXPORT _cmsGetTransformFormattersFloat(struct _cmstransform_struct *CMMcargo, cmsFormatterFloat* FromInput, cmsFormatterFloat* ToOutput);
     
    +// Retrieve original flags
    +CMSAPI cmsUInt32Number CMSEXPORT _cmsGetTransformFlags(struct _cmstransform_struct* CMMcargo);
    +
     typedef struct {
           cmsPluginBase     base;
     
    diff --git a/src/java.desktop/unix/classes/sun/java2d/xr/XRGraphicsConfig.java b/src/java.desktop/unix/classes/sun/java2d/xr/XRGraphicsConfig.java
    index 1f53e776240..680e634cce8 100644
    --- a/src/java.desktop/unix/classes/sun/java2d/xr/XRGraphicsConfig.java
    +++ b/src/java.desktop/unix/classes/sun/java2d/xr/XRGraphicsConfig.java
    @@ -23,11 +23,6 @@
      * questions.
      */
     
    -/*
    - * To change this template, choose Tools | Templates
    - * and open the template in the editor.
    - */
    -
     package sun.java2d.xr;
     
     import java.awt.Transparency;
    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 f49f4b8f64d..355d3207273 100644
    --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp
    +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp
    @@ -3215,10 +3215,12 @@ LRESULT AwtToolkit::InvokeInputMethodFunction(UINT msg, WPARAM wParam, LPARAM lP
          * function once the DND is active; otherwise a hang is possible since DND may wait for
          * the IME completion.
          */
    +    CriticalSection::Lock lock(m_inputMethodLock);
         if (isInDoDragDropLoop) {
    -        return SendMessage(msg, wParam, lParam);
    +        SendMessage(msg, wParam, lParam);
    +        ::ResetEvent(m_inputMethodWaitEvent);
    +        return m_inputMethodData;
         } else {
    -        CriticalSection::Lock lock(m_inputMethodLock);
             if (PostMessage(msg, wParam, lParam)) {
                 ::WaitForSingleObject(m_inputMethodWaitEvent, INFINITE);
                 return m_inputMethodData;
    diff --git a/src/java.prefs/windows/classes/java/util/prefs/WindowsPreferences.java b/src/java.prefs/windows/classes/java/util/prefs/WindowsPreferences.java
    index 157c33c2bbe..e955d84779d 100644
    --- a/src/java.prefs/windows/classes/java/util/prefs/WindowsPreferences.java
    +++ b/src/java.prefs/windows/classes/java/util/prefs/WindowsPreferences.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -432,7 +432,7 @@ private WindowsPreferences(WindowsPreferences parent, String name) {
             if (result[ERROR_CODE] != ERROR_SUCCESS) {
                 logger().warning("Could not create windows registry node " +
                         byteArrayToString(windowsAbsolutePath()) +
    -                    " at root 0x" + Long.toHexString(rootNativeHandle()) +
    +                    " at root 0x" + Long.toHexString(parentNativeHandle) +
                         ". Windows RegCreateKeyEx(...) returned error code " +
                         result[ERROR_CODE] + ".");
                 isBackingStoreAvailable = false;
    @@ -458,7 +458,7 @@ private  WindowsPreferences(long rootNativeHandle, byte[] rootDirectory) {
             if (result[ERROR_CODE] != ERROR_SUCCESS) {
                 logger().warning("Could not open/create prefs root node " +
                         byteArrayToString(windowsAbsolutePath()) +
    -                    " at root 0x" + Long.toHexString(rootNativeHandle()) +
    +                    " at root 0x" + Long.toHexString(rootNativeHandle) +
                         ". Windows RegCreateKeyEx(...) returned error code " +
                         result[ERROR_CODE] + ".");
                 isBackingStoreAvailable = false;
    diff --git a/src/java.rmi/share/man/rmid.1 b/src/java.rmi/share/man/rmid.1
    index 45e75ef4a7f..576fba50042 100644
    --- a/src/java.rmi/share/man/rmid.1
    +++ b/src/java.rmi/share/man/rmid.1
    @@ -21,7 +21,7 @@
     .\"
     .\" Automatically generated by Pandoc 2.3.1
     .\"
    -.TH "RMID" "1" "2020" "JDK 16" "JDK Commands"
    +.TH "RMID" "1" "2021" "JDK 17\-ea" "JDK Commands"
     .hy
     .SH NAME
     .PP
    diff --git a/src/java.rmi/share/man/rmiregistry.1 b/src/java.rmi/share/man/rmiregistry.1
    index 9e33a66e5c5..c683afa8ff9 100644
    --- a/src/java.rmi/share/man/rmiregistry.1
    +++ b/src/java.rmi/share/man/rmiregistry.1
    @@ -21,7 +21,7 @@
     .\"
     .\" Automatically generated by Pandoc 2.3.1
     .\"
    -.TH "RMIREGISTRY" "1" "2020" "JDK 16" "JDK Commands"
    +.TH "RMIREGISTRY" "1" "2021" "JDK 17\-ea" "JDK Commands"
     .hy
     .SH NAME
     .PP
    diff --git a/src/java.scripting/share/man/jrunscript.1 b/src/java.scripting/share/man/jrunscript.1
    index 627555c93ce..dfe15f0fcb2 100644
    --- a/src/java.scripting/share/man/jrunscript.1
    +++ b/src/java.scripting/share/man/jrunscript.1
    @@ -21,7 +21,7 @@
     .\"
     .\" Automatically generated by Pandoc 2.3.1
     .\"
    -.TH "JRUNSCRIPT" "1" "2020" "JDK 16" "JDK Commands"
    +.TH "JRUNSCRIPT" "1" "2021" "JDK 17\-ea" "JDK Commands"
     .hy
     .SH NAME
     .PP
    diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/Config.java b/src/java.security.jgss/share/classes/sun/security/krb5/Config.java
    index b3254bf7a57..c575a70fa33 100644
    --- a/src/java.security.jgss/share/classes/sun/security/krb5/Config.java
    +++ b/src/java.security.jgss/share/classes/sun/security/krb5/Config.java
    @@ -167,17 +167,16 @@ private static boolean isMacosLionOrBetter() {
     
             String osVersion = GetPropertyAction.privilegedGetProperty("os.version");
             String[] fragments = osVersion.split("\\.");
    -
    -        // sanity check the "10." part of the version
    -        if (!fragments[0].equals("10")) return false;
             if (fragments.length < 2) return false;
     
    -        // check if Mac OS X 10.7(.y)
    +        // check if Mac OS X 10.7(.y) or higher
             try {
    +            int majorVers = Integer.parseInt(fragments[0]);
                 int minorVers = Integer.parseInt(fragments[1]);
    -            if (minorVers >= 7) return true;
    +            if (majorVers > 10) return true;
    +            if (majorVers == 10 && minorVers >= 7) return true;
             } catch (NumberFormatException e) {
    -            // was not an integer
    +            // were not integers
             }
     
             return false;
    diff --git a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToXMLStream.java b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToXMLStream.java
    index 9633b4ade2d..254f6acc956 100644
    --- a/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToXMLStream.java
    +++ b/src/java.xml/share/classes/com/sun/org/apache/xml/internal/serializer/ToXMLStream.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
      */
     /*
      * Licensed to the Apache Software Foundation (ASF) under one or more
    @@ -40,7 +40,7 @@
      * be viewed as internal or package private, this is not an API.
      *
      * @xsl.usage internal
    - * @LastModified: Aug 2019
    + * @LastModified: Feb 2021
      */
     public final class ToXMLStream extends ToStream
     {
    @@ -171,7 +171,7 @@ public void startDocumentInternal() throws org.xml.sax.SAXException
                         writer.write('\"');
                         writer.write(standalone);
                         writer.write("?>");
    -                    if (m_doIndent) {
    +                    if (m_doIndent || m_isStandalone) {
                             if (m_standaloneWasSpecified
                                     || getDoctypePublic() != null
                                     || getDoctypeSystem() != null
    diff --git a/src/java.xml/share/classes/module-info.java b/src/java.xml/share/classes/module-info.java
    index cb0eaedb3fa..d4d147dbac4 100644
    --- a/src/java.xml/share/classes/module-info.java
    +++ b/src/java.xml/share/classes/module-info.java
    @@ -217,9 +217,7 @@
      * isStandalone
      * indicates that the serializer should treat the output as a
      * standalone document. The property can be used to ensure a newline is written
    - * after the XML declaration when the property
    - * {@link org.w3c.dom.ls.LSSerializer#getDomConfig() format-pretty-print} is set
    - * to true. Unlike the property
    + * after the XML declaration. Unlike the property
      * {@link org.w3c.dom.ls.LSSerializer#getDomConfig() xml-declaration}, this property
      * does not have an effect on whether an XML declaration should be written out.
      * 
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java
    index b15b58080a5..6c24819bd1b 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -68,11 +68,11 @@ public class AbstractCharsetProvider
         private String packagePrefix;
     
         protected AbstractCharsetProvider() {
    -        packagePrefix = "sun.nio.cs";
    +        packagePrefix = "sun.nio.cs.";
         }
     
         protected AbstractCharsetProvider(String pkgPrefixName) {
    -        packagePrefix = pkgPrefixName;
    +        packagePrefix = pkgPrefixName.concat(".");
         }
     
         /* Add an entry to the given map, but only if no mapping yet exists
    @@ -144,7 +144,7 @@ private Charset lookup(String csn) {
             // Instantiate the charset and cache it
             try {
     
    -            Class c = Class.forName(packagePrefix + "." + cln,
    +            Class c = Class.forName(packagePrefix.concat(cln),
                                            true,
                                            this.getClass().getClassLoader());
     
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_HKSCS.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_HKSCS.java.template
    index b7fbc20e164..ebf63b9604b 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_HKSCS.java.template
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_HKSCS.java.template
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -59,11 +59,11 @@ public class Big5_HKSCS extends Charset implements HistoricallyNamedCharset
         }
     
         static class Decoder extends HKSCS.Decoder {
    -        private static DoubleByte.Decoder big5 =
    +        private static final DoubleByte.Decoder big5 =
                 (DoubleByte.Decoder)new Big5().newDecoder();
     
    -        private static char[][] b2cBmp = new char[0x100][];
    -        private static char[][] b2cSupp = new char[0x100][];
    +        private static final char[][] b2cBmp = new char[0x100][];
    +        private static final char[][] b2cSupp = new char[0x100][];
             static {
                 initb2c(b2cBmp, HKSCSMapping.b2cBmpStr);
                 initb2c(b2cSupp, HKSCSMapping.b2cSuppStr);
    @@ -75,11 +75,11 @@ public class Big5_HKSCS extends Charset implements HistoricallyNamedCharset
         }
     
         static class Encoder extends HKSCS.Encoder {
    -        private static DoubleByte.Encoder big5 =
    +        private static final DoubleByte.Encoder big5 =
                 (DoubleByte.Encoder)new Big5().newEncoder();
     
    -        static char[][] c2bBmp = new char[0x100][];
    -        static char[][] c2bSupp = new char[0x100][];
    +        static final char[][] c2bBmp = new char[0x100][];
    +        static final char[][] c2bSupp = new char[0x100][];
             static {
                 initc2b(c2bBmp, HKSCSMapping.b2cBmpStr, HKSCSMapping.pua);
                 initc2b(c2bSupp, HKSCSMapping.b2cSuppStr, null);
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_HKSCS_2001.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_HKSCS_2001.java
    index 8c3e014ec73..03f859ee512 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_HKSCS_2001.java
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_HKSCS_2001.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -56,8 +56,8 @@ private static class Decoder extends HKSCS.Decoder {
             private static DoubleByte.Decoder big5 =
                 (DoubleByte.Decoder)new Big5().newDecoder();
     
    -        private static char[][] b2cBmp = new char[0x100][];
    -        private static char[][] b2cSupp = new char[0x100][];
    +        private static final char[][] b2cBmp = new char[0x100][];
    +        private static final char[][] b2cSupp = new char[0x100][];
             static {
                 initb2c(b2cBmp, HKSCS2001Mapping.b2cBmpStr);
                 initb2c(b2cSupp, HKSCS2001Mapping.b2cSuppStr);
    @@ -72,8 +72,8 @@ private static class Encoder extends HKSCS.Encoder {
             private static DoubleByte.Encoder big5 =
                 (DoubleByte.Encoder)new Big5().newEncoder();
     
    -        static char[][] c2bBmp = new char[0x100][];
    -        static char[][] c2bSupp = new char[0x100][];
    +        static final char[][] c2bBmp = new char[0x100][];
    +        static final char[][] c2bSupp = new char[0x100][];
             static {
                 initc2b(c2bBmp, HKSCS2001Mapping.b2cBmpStr,
                         HKSCS2001Mapping.pua);
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_Solaris.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_Solaris.java.template
    index 2099fbb1ad3..2c88b15f29b 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_Solaris.java.template
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/Big5_Solaris.java.template
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -50,27 +50,21 @@ public class Big5_Solaris extends Charset implements HistoricallyNamedCharset
         }
     
         public CharsetDecoder newDecoder() {
    -        initb2c();
    -        return new  DoubleByte.Decoder(this, b2c, b2cSB, 0x40, 0xfe, true);
    +        return new DoubleByte.Decoder(this, Holder.b2c, Holder.b2cSB, 0x40, 0xfe, true);
         }
     
         public CharsetEncoder newEncoder() {
    -        initc2b();
    -        return new DoubleByte.Encoder(this, c2b, c2bIndex, true);
    +        return new DoubleByte.Encoder(this, Holder.c2b, Holder.c2bIndex, true);
         }
     
    -    static char[][] b2c;
    -    static char[] b2cSB;
    -    private static volatile boolean b2cInitialized = false;
    +    private static class Holder {
    +        static final char[][] b2c;
    +        static final char[] b2cSB;
    +        static final char[] c2b;
    +        static final char[] c2bIndex;
     
    -    static void initb2c() {
    -        if (b2cInitialized)
    -            return;
    -        synchronized (Big5_Solaris.class) {
    -            if (b2cInitialized)
    -                return;
    -            Big5.initb2c();
    -            b2c = Big5.b2c.clone();
    +        static {
    +            b2c = Big5.DecodeHolder.b2c.clone();
                 // Big5 Solaris implementation has 7 additional mappings
                 int[] sol = new int[] {
                     0xF9D6, 0x7881,
    @@ -88,25 +82,11 @@ public class Big5_Solaris extends Charset implements HistoricallyNamedCharset
                 for (int i = 0; i < sol.length;) {
                     b2c[0xf9][sol[i++] & 0xff - 0x40] = (char)sol[i++];
                 }
    -            b2cSB = Big5.b2cSB;
    -            b2cInitialized = true;
    -        }
    -    }
    +            b2cSB = Big5.DecodeHolder.b2cSB;
     
    -    static char[] c2b;
    -    static char[] c2bIndex;
    -    private static volatile boolean c2bInitialized = false;
    -
    -    static void initc2b() {
    -        if (c2bInitialized)
    -            return;
    -        synchronized (Big5_Solaris.class) {
    -            if (c2bInitialized)
    -                return;
    -            Big5.initc2b();
    -            c2b = Big5.c2b.clone();
    -            c2bIndex = Big5.c2bIndex.clone();
    -            int[] sol = new int[] {
    +            c2b = Big5.EncodeHolder.c2b.clone();
    +            c2bIndex = Big5.EncodeHolder.c2bIndex.clone();
    +            sol = new int[] {
                     0x7881, 0xF9D6,
                     0x92B9, 0xF9D7,
                     0x88CF, 0xF9D8,
    @@ -121,7 +101,6 @@ public class Big5_Solaris extends Charset implements HistoricallyNamedCharset
                     // to the appropriate place.
                     c2b[c2bIndex[c >> 8] + (c & 0xff)] = (char)sol[i++];
                 }
    -            c2bInitialized = true;
             }
         }
     }
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP.java.template
    index 1a1a9affe83..8eed590c836 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP.java.template
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_JP.java.template
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -113,14 +113,10 @@ public class EUC_JP
                 byte[] sa = src.array();
                 int sp = src.arrayOffset() + src.position();
                 int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
     
                 char[] da = dst.array();
                 int dp = dst.arrayOffset() + dst.position();
                 int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
     
                 int b1 = 0, b2 = 0;
                 int inputSize = 0;
    @@ -296,13 +292,10 @@ public class EUC_JP
                 char[] sa = src.array();
                 int sp = src.arrayOffset() + src.position();
                 int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
    +
                 byte[] da = dst.array();
                 int dp = dst.arrayOffset() + dst.position();
                 int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
     
                 int outputSize = 0;
                 byte[]  outputByte;
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_TW.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_TW.java.template
    index 14620a2a40b..aa7586ae067 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_TW.java.template
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/EUC_TW.java.template
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -146,6 +146,19 @@ public class EUC_TW extends Charset implements HistoricallyNamedCharset
                return b >= b1Min && b <= b1Max;
             }
     
    +        public static char decodeSingleOrReplace(int b1, int b2, int p, char replace) {
    +            if (b1 < b1Min || b1 > b1Max || b2 < b2Min || b2 > b2Max)
    +                return replace;
    +            int index = (b1 - b1Min) * dbSegSize + b2 - b2Min;
    +            char c = b2c[p].charAt(index);
    +            if (c == UNMAPPABLE_DECODING)
    +                return replace;
    +            if ((b2cIsSupp[index] & (1 << p)) == 0) {
    +                return c;
    +            }
    +            return replace;
    +        }
    +
             static char[] decode(int b1, int b2, int p, char[] c1, char[] c2)
             {
                 if (b1 < b1Min || b1 > b1Max || b2 < b2Min || b2 > b2Max)
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/GB18030.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/GB18030.java.template
    index 436d9e79742..fb3b8fb824f 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/GB18030.java.template
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/GB18030.java.template
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -12332,14 +12332,10 @@ public class GB18030
                 byte[] sa = src.array();
                 int sp = src.arrayOffset() + src.position();
                 int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
     
                 char[] da = dst.array();
                 int dp = dst.arrayOffset() + dst.position();
                 int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
     
                 int inputSize = 1;
     
    @@ -12585,13 +12581,10 @@ public class GB18030
                 char[] sa = src.array();
                 int sp = src.arrayOffset() + src.position();
                 int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
    +
                 byte[] da = dst.array();
                 int dp = dst.arrayOffset() + dst.position();
                 int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
     
                 int condensedKey = 0;  // expands to a four byte sequence
                 int hiByte = 0, loByte = 0;
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM29626C.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM29626C.java.template
    index 1328c0927dd..4a35873f524 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM29626C.java.template
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM29626C.java.template
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -67,23 +67,23 @@ public class IBM29626C
         static class Decoder extends CharsetDecoder
             implements DelegatableDecoder {
     
    -        final static SingleByte.Decoder DEC0201 =
    +        static final SingleByte.Decoder DEC0201 =
                 (SingleByte.Decoder)new JIS_X_0201().newDecoder();
     
    -        final static DoubleByte.Decoder DEC0208 =
    +        static final DoubleByte.Decoder DEC0208 =
                 (DoubleByte.Decoder)new JIS_X_0208().newDecoder();
     
    -        final static DoubleByte.Decoder DEC0212 =
    +        static final DoubleByte.Decoder DEC0212 =
                 (DoubleByte.Decoder)new JIS_X_0212().newDecoder();
     
    -        final static DoubleByte.Encoder ibm943 =
    +        static final DoubleByte.Encoder ibm943 =
                 (DoubleByte.Encoder)new IBM943().newEncoder();
     
             private final SingleByte.Decoder dec0201;
             private final DoubleByte.Decoder dec0208;
             private final DoubleByte.Decoder dec0212;
     
    -        private final String G2_b =
    +        private static final String G2_b =
                 "\uA1F1\uA1F2\uA2CC\uADA1\uADA2\uADA3\uADA4\uADA5\uADA6\uADA7"+
                 "\uADA8\uADA9\uADAA\uADAB\uADAC\uADAD\uADAE\uADAF\uADB0\uADB1"+
                 "\uADB2\uADB3\uADB4\uADB5\uADB6\uADB7\uADB8\uADB9\uADBA\uADBB"+
    @@ -94,7 +94,7 @@ public class IBM29626C
                 "\uADED\uADEE\uADEF\uADF0\uADF1\uADF2\uADF3\uADF4\uADF5\uADF6"+
                 "\uADF7\uADF8\uADF9\uADFA\uADFB\uADFC";
     
    -        private final String G2_c =
    +        private static final String G2_c =
                 "\uFFE0\uFFE1\uFFE2\u2460\u2461\u2462\u2463\u2464\u2465\u2466"+
                 "\u2467\u2468\u2469\u246A\u246B\u246C\u246D\u246E\u246F\u2470"+
                 "\u2471\u2472\u2473\u2160\u2161\u2162\u2163\u2164\u2165\u2166"+
    @@ -105,7 +105,7 @@ public class IBM29626C
                 "\u337E\u337D\u337C\u2252\u2261\u222B\u222E\u2211\u221A\u22A5"+
                 "\u2220\u221F\u22BF\u2235\u2229\u222A";
     
    -        private final String G3_b =
    +        private static final String G3_b =
                 "\uF3B8\uF3B9\uF3AB\uF3AC\uF3AD\uF3AE\uF3AF\uF3B0\uF3B1\uF3B2"+
                 "\uF3B3\uF3B4\uF3A1\uF3A2\uF3A3\uF3A4\uF3A5\uF3A6\uF3A7\uF3A8"+
                 "\uF3A9\uF3AA\uF3B7\uF3B8\uF4A2\uF4A3\uF4A4\uF4A5\uF4A6\uF4A8"+
    @@ -118,7 +118,7 @@ public class IBM29626C
                 "\uF4D6\uF4D8\uF4DA\uF4DB\uF4DE\uF4E2\uF4E3\uF4E4\uF4E6\uF4E8"+
                 "\uF4E9\uF4EC\uF4F1\uF4F2\uF4F3\uF4F7\uF3B6\uF3B5";
     
    -        private final String G3_c =
    +        private static final String G3_c =
                 "\u2116\u2121\u2160\u2161\u2162\u2163\u2164\u2165\u2166\u2167"+
                 "\u2168\u2169\u2170\u2171\u2172\u2173\u2174\u2175\u2176\u2177"+
                 "\u2178\u2179\u3231\u00A6\u4EFC\u50F4\u51EC\u5307\u5324\u548A"+
    @@ -164,7 +164,7 @@ public class IBM29626C
                 return UNMAPPABLE_DECODING;
             }
     
    -        final static String g1_c = "\u00a2\u00a3\u00ac\\\u007e";
    +        static final String g1_c = "\u00a2\u00a3\u00ac\\\u007e";
     
             protected char decodeDouble(int byte1, int byte2) {
                 if (byte1 == 0x8e) {
    @@ -212,14 +212,10 @@ public class IBM29626C
                 byte[] sa = src.array();
                 int sp = src.arrayOffset() + src.position();
                 int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
     
                 char[] da = dst.array();
                 int dp = dst.arrayOffset() + dst.position();
                 int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
     
                 int b1 = 0, b2 = 0;
                 int inputSize = 0;
    @@ -322,16 +318,16 @@ public class IBM29626C
     
         static class Encoder extends CharsetEncoder {
     
    -        final static SingleByte.Encoder ENC0201 =
    +        static final SingleByte.Encoder ENC0201 =
                 (SingleByte.Encoder)new JIS_X_0201().newEncoder();
     
    -        final static DoubleByte.Encoder ENC0208 =
    +        static final DoubleByte.Encoder ENC0208 =
                 (DoubleByte.Encoder)new JIS_X_0208().newEncoder();
     
    -        final static DoubleByte.Encoder ENC0212 =
    +        static final DoubleByte.Encoder ENC0212 =
                 (DoubleByte.Encoder)new JIS_X_0212().newEncoder();
     
    -        final static DoubleByte.Encoder ibm943 =
    +        static final DoubleByte.Encoder ibm943 =
                 (DoubleByte.Encoder)new IBM943().newEncoder();
     
             private final Surrogate.Parser sgp = new Surrogate.Parser();
    @@ -340,7 +336,7 @@ public class IBM29626C
             private final DoubleByte.Encoder enc0208;
             private final DoubleByte.Encoder enc0212;
     
    -        private final String G2_c =
    +        private static final String G2_c =
                 "\u2015\u2211\u221F\u2225\u222E\u22BF\u2460\u2461\u2462\u2463"+
                 "\u2464\u2465\u2466\u2467\u2468\u2469\u246A\u246B\u246C\u246D"+
                 "\u246E\u246F\u2470\u2471\u2472\u2473\u301D\u301F\u3232\u3239"+
    @@ -353,7 +349,7 @@ public class IBM29626C
                 "\u881F\u8EC0\u91AC\u91B1\u9830\u9839\u985A\u9A52\u9DD7\u9E7C"+
                 "\u9EB4\u9EB5\uFF0D\uFF5E\uFFE0\uFFE1\uFFE2";
     
    -        private final String G2_b =
    +        private static final String G2_b =
                 "\uA1BD\uADF4\uADF8\uA1C2\uADF3\uADF9\uADA1\uADA2\uADA3\uADA4"+
                 "\uADA5\uADA6\uADA7\uADA8\uADA9\uADAA\uADAB\uADAC\uADAD\uADAE"+
                 "\uADAF\uADB0\uADB1\uADB2\uADB3\uADB4\uADE0\uADE1\uADEB\uADEC"+
    @@ -366,7 +362,7 @@ public class IBM29626C
                 "\uCFB9\uB6ED\uBEDF\uC8B0\uCBCB\uF0F8\uC5BF\uC2CD\uB2AA\uB8B4"+
                 "\uB9ED\uCCCD\uA1DD\uA1C1\uA1F1\uA1F2\uA2CC";
     
    -        private final String G3_c =
    +        private static final String G3_c =
                 "\u2116\u2121\u2160\u2161\u2162\u2163\u2164\u2165\u2166\u2167"+
                 "\u2168\u2169\u2170\u2171\u2172\u2173\u2174\u2175\u2176\u2177"+
                 "\u2178\u2179\u3231\u4EFC\u50F4\u51EC\u5307\u5324\u548A\u5759"+
    @@ -379,7 +375,7 @@ public class IBM29626C
                 "\uFA1F\uFA20\uFA21\uFA22\uFA23\uFA24\uFA25\uFA26\uFA27\uFA28"+
                 "\uFA29\uFA2A\uFA2B\uFA2C\uFA2D\uFF02\uFF07\uFFE4";
     
    -        private final String G3_b =
    +        private static final String G3_b =
                 "\uF3B8\uF3B9\uF3AB\uF3AC\uF3AD\uF3AE\uF3AF\uF3B0\uF3B1\uF3B2"+
                 "\uF3B3\uF3B4\uF3A1\uF3A2\uF3A3\uF3A4\uF3A5\uF3A6\uF3A7\uF3A8"+
                 "\uF3A9\uF3AA\uF3B7\uF4A2\uF4A3\uF4A4\uF4A5\uF4A6\uF4A8\uF4A9"+
    @@ -412,7 +408,7 @@ public class IBM29626C
                        encodeDouble(c) != UNMAPPABLE_ENCODING;
             }
     
    -        private final static String G1_c = "\u00A2\u00A3\u00AC";
    +        private static final String G1_c = "\u00A2\u00A3\u00AC";
     
             protected int encodeSingle(char inputChar, byte[] outputByte) {
                 if (inputChar >= 0x80 && inputChar < 0x8e) {
    @@ -484,13 +480,10 @@ public class IBM29626C
                 char[] sa = src.array();
                 int sp = src.arrayOffset() + src.position();
                 int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
    +
                 byte[] da = dst.array();
                 int dp = dst.arrayOffset() + dst.position();
                 int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
     
                 int outputSize = 0;
                 byte[]  outputByte;
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM33722.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM33722.java
    index 6af1d2189c1..7cdf17797d0 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM33722.java
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM33722.java
    @@ -1,6 +1,5 @@
    -
     /*
    - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -65,15 +64,8 @@ public CharsetEncoder newEncoder() {
     
         protected static class Decoder extends CharsetDecoder {
     
    -        private final int G0 = 0;
    -        private final int G1 = 1;
    -        private final int G2 = 2;
    -        private final int G3 = 3;
    -        private final int G4 = 4;
    -        private final int SS2 =  0x8E;
    -        private final int SS3 =  0x8F;
    -
    -        private int firstByte, state;
    +        private static final int SS2 =  0x8E;
    +        private static final int SS3 =  0x8F;
     
             public Decoder(Charset cs) {
                     super(cs, 1.0f, 1.0f);
    @@ -83,19 +75,16 @@ private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
                 byte[] sa = src.array();
                 int sp = src.arrayOffset() + src.position();
                 int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
    +
                 char[] da = dst.array();
                 int dp = dst.arrayOffset() + dst.position();
                 int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
     
                 try {
                 while (sp < sl) {
                     int byte1, byte2;
                     int inputSize = 1;
    -                char outputChar = '\uFFFD';
    +                char outputChar;
                     byte1 = sa[sp] & 0xff;
     
                     if (byte1 == SS2) {
    @@ -157,7 +146,7 @@ private CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) {
                     while (src.hasRemaining()) {
                         int byte1, byte2;
                         int inputSize = 1;
    -                    char outputChar = '\uFFFD';
    +                    char outputChar;
                         byte1 = src.get() & 0xff;
     
                         if (byte1 == SS2) {
    @@ -212,16 +201,16 @@ private CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) {
             }
     
             protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
    -            if (true && src.hasArray() && dst.hasArray())
    +            if (src.hasArray() && dst.hasArray())
                     return decodeArrayLoop(src, dst);
                 else
                     return decodeBufferLoop(src, dst);
             }
     
    -        private final static String byteToCharTable;
    -        private final static String mappingTableG1;
    -        private final static String mappingTableG2;
    -        private final static String mappingTableG3;
    +        private static final String byteToCharTable;
    +        private static final String mappingTableG1;
    +        private static final String mappingTableG2;
    +        private static final String mappingTableG3;
             static {
                 byteToCharTable =
                     "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007" +
    @@ -2749,9 +2738,9 @@ public Encoder(Charset cs) {
                     21792,   192,    73, 21824,    41,  2344,  2344,     0,
             };
     
    -        private final static String index2;
    -        private final static String index2a;
    -        private final static String index2b;
    +        private static final String index2;
    +        private static final String index2a;
    +        private static final String index2b;
             static {
                 index2 =
                     "\u0000\uA1F1\u0000\uA1F2\u0000\uA2CC\u0000\uA1B1\u0000\uA2C3" + //     0 -     4
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM834.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM834.java.template
    index 4d3f4b1421f..468a0cc74c8 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM834.java.template
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM834.java.template
    @@ -1,6 +1,5 @@
    -
     /*
    - * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -49,20 +48,18 @@ public class IBM834 extends Charset
         }
     
         public CharsetDecoder newDecoder() {
    -        IBM933.initb2c();
             return new DoubleByte.Decoder_DBCSONLY(
    -            this, IBM933.b2c, null, 0x40, 0xfe);  // hardcode the b2min/max
    +            this, IBM933.DecodeHolder.b2c, null, 0x40, 0xfe);  // hardcode the b2min/max
         }
     
         public CharsetEncoder newEncoder() {
    -        IBM933.initc2b();
             return new Encoder(this);
         }
     
         protected static class Encoder extends DoubleByte.Encoder_DBCSONLY {
             public Encoder(Charset cs) {
                 super(cs, new byte[] {(byte)0xfe, (byte)0xfe},
    -                  IBM933.c2b, IBM933.c2bIndex, false);
    +                  IBM933.EncodeHolder.c2b, IBM933.EncodeHolder.c2bIndex, false);
             }
     
             public int encodeChar(char ch) {
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM942C.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM942C.java.template
    index 26b7cd14b99..b0f6ad3e031 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM942C.java.template
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM942C.java.template
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -50,44 +50,43 @@ public class IBM942C extends Charset implements HistoricallyNamedCharset
     
         public CharsetDecoder newDecoder() {
             return new DoubleByte.Decoder(this,
    -                                      IBM942.b2c,
    -                                      b2cSB,
    +                                      IBM942.DecodeHolder.b2c,
    +                                      Holder.b2cSB,
                                           0x40,
                                           0xfc);
         }
     
         public CharsetEncoder newEncoder() {
    -        return new DoubleByte.Encoder(this, c2b, c2bIndex);
    +        return new DoubleByte.Encoder(this, Holder.c2b, Holder.c2bIndex);
         }
     
    -    final static char[] b2cSB;
    -    final static char[] c2b;
    -    final static char[] c2bIndex;
    +    private static class Holder {
    +        static final char[] b2cSB;
    +        static final char[] c2b;
    +        static final char[] c2bIndex;
     
    -    static {
    -        IBM942.initb2c();
    +        static {
    +            // the mappings need udpate are
    +            //    u+001a  <-> 0x1a
    +            //    u+001c  <-> 0x1c
    +            //    u+005c  <-> 0x5c
    +            //    u+007e  <-> 0x7e
    +            //    u+007f  <-> 0x7f
     
    -        // the mappings need udpate are
    -        //    u+001a  <-> 0x1a
    -        //    u+001c  <-> 0x1c
    -        //    u+005c  <-> 0x5c
    -        //    u+007e  <-> 0x7e
    -        //    u+007f  <-> 0x7f
    +            b2cSB = Arrays.copyOf(IBM942.DecodeHolder.b2cSB, IBM942.DecodeHolder.b2cSB.length);
    +            b2cSB[0x1a] = 0x1a;
    +            b2cSB[0x1c] = 0x1c;
    +            b2cSB[0x5c] = 0x5c;
    +            b2cSB[0x7e] = 0x7e;
    +            b2cSB[0x7f] = 0x7f;
     
    -        b2cSB = Arrays.copyOf(IBM942.b2cSB, IBM942.b2cSB.length);
    -        b2cSB[0x1a] = 0x1a;
    -        b2cSB[0x1c] = 0x1c;
    -        b2cSB[0x5c] = 0x5c;
    -        b2cSB[0x7e] = 0x7e;
    -        b2cSB[0x7f] = 0x7f;
    -
    -        IBM942.initc2b();
    -        c2b = Arrays.copyOf(IBM942.c2b, IBM942.c2b.length);
    -        c2bIndex = Arrays.copyOf(IBM942.c2bIndex, IBM942.c2bIndex.length);
    -        c2b[c2bIndex[0] + 0x1a] = 0x1a;
    -        c2b[c2bIndex[0] + 0x1c] = 0x1c;
    -        c2b[c2bIndex[0] + 0x5c] = 0x5c;
    -        c2b[c2bIndex[0] + 0x7e] = 0x7e;
    -        c2b[c2bIndex[0] + 0x7f] = 0x7f;
    +            c2b = Arrays.copyOf(IBM942.EncodeHolder.c2b, IBM942.EncodeHolder.c2b.length);
    +            c2bIndex = Arrays.copyOf(IBM942.EncodeHolder.c2bIndex, IBM942.EncodeHolder.c2bIndex.length);
    +            c2b[c2bIndex[0] + 0x1a] = 0x1a;
    +            c2b[c2bIndex[0] + 0x1c] = 0x1c;
    +            c2b[c2bIndex[0] + 0x5c] = 0x5c;
    +            c2b[c2bIndex[0] + 0x7e] = 0x7e;
    +            c2b[c2bIndex[0] + 0x7f] = 0x7f;
    +        }
         }
     }
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM943C.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM943C.java.template
    index 5b145857c95..b824319d60e 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM943C.java.template
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM943C.java.template
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -50,36 +50,35 @@ public class IBM943C extends Charset implements HistoricallyNamedCharset
     
         public CharsetDecoder newDecoder() {
             return new DoubleByte.Decoder(this,
    -                                      IBM943.b2c,
    -                                      b2cSB,
    +                                      IBM943.DecodeHolder.b2c,
    +                                      Holder.b2cSB,
                                           0x40,
                                           0xfc);
         }
     
         public CharsetEncoder newEncoder() {
    -        return new DoubleByte.Encoder(this, c2b, c2bIndex);
    +        return new DoubleByte.Encoder(this, Holder.c2b, Holder.c2bIndex);
         }
     
    -    final static char[] b2cSB;
    -    final static char[] c2b;
    -    final static char[] c2bIndex;
    +    private static class Holder {
    +        static final char[] b2cSB;
    +        static final char[] c2b;
    +        static final char[] c2bIndex;
     
    -    static {
    -        IBM943.initb2c();
    -        b2cSB = new char[0x100];
    -        for (int i = 0; i < 0x80; i++) {
    -            b2cSB[i] = (char)i;
    -        }
    -        for (int i = 0x80; i < 0x100; i++) {
    -            b2cSB[i] = IBM943.b2cSB[i];
    -        }
    -
    -        IBM943.initc2b();
    -        c2b = Arrays.copyOf(IBM943.c2b, IBM943.c2b.length);
    -        c2bIndex = Arrays.copyOf(IBM943.c2bIndex, IBM943.c2bIndex.length);
    -        for (char c = '\0'; c < '\u0080'; ++c) {
    -            int index = c2bIndex[c >> 8];
    -            c2b[index + (c & 0xff)] = c;
    +        static {
    +            b2cSB = new char[0x100];
    +            for (int i = 0; i < 0x80; i++) {
    +                b2cSB[i] = (char)i;
    +            }
    +            for (int i = 0x80; i < 0x100; i++) {
    +                b2cSB[i] = IBM943.DecodeHolder.b2cSB[i];
    +            }
    +            c2b = Arrays.copyOf(IBM943.EncodeHolder.c2b, IBM943.EncodeHolder.c2b.length);
    +            c2bIndex = Arrays.copyOf(IBM943.EncodeHolder.c2bIndex, IBM943.EncodeHolder.c2bIndex.length);
    +            for (char c = '\0'; c < '\u0080'; ++c) {
    +                int index = c2bIndex[c >> 8];
    +                c2b[index + (c & 0xff)] = c;
    +            }
             }
         }
     }
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM949C.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM949C.java.template
    index d930cb11c4b..e46709576df 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM949C.java.template
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM949C.java.template
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -50,35 +50,35 @@ public class IBM949C extends Charset implements HistoricallyNamedCharset
     
         public CharsetDecoder newDecoder() {
             return new DoubleByte.Decoder(this,
    -                                      IBM949.b2c,
    -                                      b2cSB,
    +                                      IBM949.DecodeHolder.b2c,
    +                                      Holder.b2cSB,
                                           0xa1,
                                           0xfe);
         }
     
         public CharsetEncoder newEncoder() {
    -        return new DoubleByte.Encoder(this, c2b, c2bIndex);
    +        return new DoubleByte.Encoder(this, Holder.c2b, Holder.c2bIndex);
         }
     
    -    final static char[] b2cSB;
    -    final static char[] c2b;
    -    final static char[] c2bIndex;
    +    private static class Holder {
    +        static final char[] b2cSB;
    +        static final char[] c2b;
    +        static final char[] c2bIndex;
     
    -    static {
    -        IBM949.initb2c();
    -        b2cSB = new char[0x100];
    -        for (int i = 0; i < 0x80; i++) {
    -            b2cSB[i] = (char)i;
    -        }
    -        for (int i = 0x80; i < 0x100; i++) {
    -            b2cSB[i] = IBM949.b2cSB[i];
    -        }
    -        IBM949.initc2b();
    -        c2b = Arrays.copyOf(IBM949.c2b, IBM949.c2b.length);
    -        c2bIndex = Arrays.copyOf(IBM949.c2bIndex, IBM949.c2bIndex.length);
    -        for (char c = '\0'; c < '\u0080'; ++c) {
    -            int index = c2bIndex[c >> 8];
    -            c2b[index + (c & 0xff)] = c;
    +        static {
    +            b2cSB = new char[0x100];
    +            for (int i = 0; i < 0x80; i++) {
    +                b2cSB[i] = (char)i;
    +            }
    +            for (int i = 0x80; i < 0x100; i++) {
    +                b2cSB[i] = IBM949.DecodeHolder.b2cSB[i];
    +            }
    +            c2b = Arrays.copyOf(IBM949.EncodeHolder.c2b, IBM949.EncodeHolder.c2b.length);
    +            c2bIndex = Arrays.copyOf(IBM949.EncodeHolder.c2bIndex, IBM949.EncodeHolder.c2bIndex.length);
    +            for (char c = '\0'; c < '\u0080'; ++c) {
    +                int index = c2bIndex[c >> 8];
    +                c2b[index + (c & 0xff)] = c;
    +            }
             }
         }
     }
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM964.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM964.java.template
    index b4cf94a2952..50f40aa6805 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM964.java.template
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM964.java.template
    @@ -1,6 +1,5 @@
    -
     /*
    - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -76,13 +75,10 @@ public class IBM964
                 byte[] sa = src.array();
                 int sp = src.arrayOffset() + src.position();
                 int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
    +
                 char[] da = dst.array();
                 int dp = dst.arrayOffset() + dst.position();
                 int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
     
                 try {
                 while (sp < sl) {
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISCII91.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISCII91.java
    index 1e691599197..54933058e73 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISCII91.java
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISCII91.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -500,14 +500,10 @@ private CoderResult decodeArrayLoop(ByteBuffer src,
                 byte[] sa = src.array();
                 int sp = src.arrayOffset() + src.position();
                 int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
     
                 char[] da = dst.array();
                 int dp = dst.arrayOffset() + dst.position();
                 int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
     
                 try {
                     while (sp < sl) {
    @@ -821,15 +817,10 @@ private CoderResult encodeArrayLoop(CharBuffer src,
                 char[] sa = src.array();
                 int sp = src.arrayOffset() + src.position();
                 int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
    +
                 byte[] da = dst.array();
                 int dp = dst.arrayOffset() + dst.position();
                 int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
    -
    -            int outputSize = 0;
     
                 try {
                     char inputChar;
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022.java
    index 7c56c8e5fbc..041ab301d64 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022.java
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -39,359 +39,33 @@
     abstract class ISO2022
         extends Charset
     {
    -
    -    private static final byte ISO_ESC = 0x1b;
    -    private static final byte ISO_SI = 0x0f;
    -    private static final byte ISO_SO = 0x0e;
    -    private static final byte ISO_SS2_7 = 0x4e;
    -    private static final byte ISO_SS3_7 = 0x4f;
    -    private static final byte MSB = (byte)0x80;
    -    private static final char REPLACE_CHAR = '\uFFFD';
    -    private static final byte minDesignatorLength = 3;
    -
         public ISO2022(String csname, String[] aliases) {
             super(csname, aliases);
         }
     
    -    public CharsetDecoder newDecoder() {
    -        return new Decoder(this);
    -    }
    -
    -    public CharsetEncoder newEncoder() {
    -        return new Encoder(this);
    -    }
    -
    -    protected static class Decoder extends CharsetDecoder {
    -
    -        // Value to be filled by subclass
    -        protected byte SODesig[][];
    -        protected byte SS2Desig[][] = null;
    -        protected byte SS3Desig[][] = null;
    -
    -        protected CharsetDecoder SODecoder[];
    -        protected CharsetDecoder SS2Decoder[] = null;
    -        protected CharsetDecoder SS3Decoder[] = null;
    +    public abstract CharsetDecoder newDecoder();
     
    -        private static final byte SOFlag = 0;
    -        private static final byte SS2Flag = 1;
    -        private static final byte SS3Flag = 2;
    +    public abstract CharsetEncoder newEncoder();
     
    -        private int curSODes, curSS2Des, curSS3Des;
    -        private boolean shiftout;
    -        private CharsetDecoder tmpDecoder[];
    -
    -        protected Decoder(Charset cs) {
    -            super(cs, 1.0f, 1.0f);
    -        }
    -
    -        protected void implReset() {
    -            curSODes = 0;
    -            curSS2Des = 0;
    -            curSS3Des = 0;
    -            shiftout = false;
    -        }
    -
    -        private char decode(byte byte1, byte byte2, byte shiftFlag)
    -        {
    -            byte1 |= MSB;
    -            byte2 |= MSB;
    -
    -            byte[] tmpByte = { byte1,byte2 };
    -            char[] tmpChar = new char[1];
    -            int     i = 0,
    -                    tmpIndex = 0;
    -
    -            switch(shiftFlag) {
    -            case SOFlag:
    -                tmpIndex = curSODes;
    -                tmpDecoder = SODecoder;
    -                break;
    -            case SS2Flag:
    -                tmpIndex = curSS2Des;
    -                tmpDecoder = SS2Decoder;
    -                break;
    -            case SS3Flag:
    -                tmpIndex = curSS3Des;
    -                tmpDecoder = SS3Decoder;
    -                break;
    -            }
    +    // No default Decoder implementation is provided here; the concrete
    +    // encodings differ enough that most had been specialized for
    +    // performance reasons, leaving the generic implementation that existed
    +    // here before JDK-8261418 unused except by ISO2022_KR. As both a
    +    // simplification and an optimization the implementation was moved
    +    // there and specialized.
     
    -            if (tmpDecoder != null) {
    -                for(i = 0; i < tmpDecoder.length; i++) {
    -                    if(tmpIndex == i) {
    -                        try {
    -                            ByteBuffer bb = ByteBuffer.wrap(tmpByte,0,2);
    -                            CharBuffer cc = CharBuffer.wrap(tmpChar,0,1);
    -                            tmpDecoder[i].decode(bb, cc, true);
    -                            cc.flip();
    -                            return cc.get();
    -                        } catch (Exception e) {}
    -                    }
    -                }
    -            }
    -            return REPLACE_CHAR;
    -        }
    -
    -        private int findDesig(byte[] in, int sp, int sl, byte[][] desigs) {
    -            if (desigs == null) return -1;
    -            int i = 0;
    -            while (i < desigs.length) {
    -                if (desigs[i] != null && sl - sp >= desigs[i].length) {
    -                    int j = 0;
    -                    while (j < desigs[i].length && in[sp+j] == desigs[i][j]) { j++; }
    -                    if (j == desigs[i].length)
    -                        return i;
    -                }
    -                i++;
    -            }
    -            return -1;
    -        }
    -
    -        private int findDesigBuf(ByteBuffer in, byte[][] desigs) {
    -            if (desigs == null) return -1;
    -            int i = 0;
    -            while (i < desigs.length) {
    -                if (desigs[i] != null && in.remaining() >= desigs[i].length) {
    -                    int j = 0;
    -                    in.mark();
    -                    while (j < desigs[i].length && in.get() == desigs[i][j]) { j++; }
    -                    if (j == desigs[i].length)
    -                        return i;
    -                    in.reset();
    -                }
    -                i++;
    -            }
    -            return -1;
    -        }
    -
    -        private CoderResult decodeArrayLoop(ByteBuffer src,
    -                                            CharBuffer dst)
    -        {
    -            byte[] sa = src.array();
    -            int sp = src.arrayOffset() + src.position();
    -            int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
    -
    -            char[] da = dst.array();
    -            int dp = dst.arrayOffset() + dst.position();
    -            int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
    -
    -            int b1 = 0, b2 = 0, b3 = 0;
    -
    -            try {
    -                while (sp < sl) {
    -                    b1 = sa[sp] & 0xff;
    -                    int inputSize = 1;
    -                    switch (b1) {
    -                        case ISO_SO:
    -                            shiftout = true;
    -                            inputSize = 1;
    -                            break;
    -                        case ISO_SI:
    -                            shiftout = false;
    -                            inputSize = 1;
    -                            break;
    -                        case ISO_ESC:
    -                            if (sl - sp - 1 < minDesignatorLength)
    -                                return CoderResult.UNDERFLOW;
    -
    -                            int desig = findDesig(sa, sp + 1, sl, SODesig);
    -                            if (desig != -1) {
    -                                curSODes = desig;
    -                                inputSize = SODesig[desig].length + 1;
    -                                break;
    -                            }
    -                            desig = findDesig(sa, sp + 1, sl, SS2Desig);
    -                            if (desig != -1) {
    -                                curSS2Des = desig;
    -                                inputSize = SS2Desig[desig].length + 1;
    -                                break;
    -                            }
    -                            desig = findDesig(sa, sp + 1, sl, SS3Desig);
    -                            if (desig != -1) {
    -                                curSS3Des = desig;
    -                                inputSize = SS3Desig[desig].length + 1;
    -                                break;
    -                            }
    -                            if (sl - sp < 2)
    -                                return CoderResult.UNDERFLOW;
    -                            b1 = sa[sp + 1];
    -                            switch(b1) {
    -                            case ISO_SS2_7:
    -                                if (sl - sp < 4)
    -                                    return CoderResult.UNDERFLOW;
    -                                b2 = sa[sp +2];
    -                                b3 = sa[sp +3];
    -                                if (dl - dp <1)
    -                                    return CoderResult.OVERFLOW;
    -                                da[dp] = decode((byte)b2,
    -                                                (byte)b3,
    -                                                SS2Flag);
    -                                dp++;
    -                                inputSize = 4;
    -                                break;
    -                            case ISO_SS3_7:
    -                                if (sl - sp < 4)
    -                                    return CoderResult.UNDERFLOW;
    -                                b2 = sa[sp + 2];
    -                                b3 = sa[sp + 3];
    -                                if (dl - dp <1)
    -                                    return CoderResult.OVERFLOW;
    -                                da[dp] = decode((byte)b2,
    -                                                (byte)b3,
    -                                                SS3Flag);
    -                                dp++;
    -                                inputSize = 4;
    -                                break;
    -                            default:
    -                                return CoderResult.malformedForLength(2);
    -                            }
    -                            break;
    -                        default:
    -                            if (dl - dp < 1)
    -                                return CoderResult.OVERFLOW;
    -                            if (!shiftout) {
    -                                da[dp++]=(char)(sa[sp] & 0xff);
    -                            } else {
    -                                if (dl - dp < 1)
    -                                    return CoderResult.OVERFLOW;
    -                                if (sl - sp < 2)
    -                                    return CoderResult.UNDERFLOW;
    -                                b2 = sa[sp+1] & 0xff;
    -                                da[dp++] = decode((byte)b1,
    -                                                  (byte)b2,
    -                                                   SOFlag);
    -                                inputSize = 2;
    -                            }
    -                            break;
    -                    }
    -                    sp += inputSize;
    -                }
    -                return CoderResult.UNDERFLOW;
    -            } finally {
    -                src.position(sp - src.arrayOffset());
    -                dst.position(dp - dst.arrayOffset());
    -            }
    -        }
    -
    -        private CoderResult decodeBufferLoop(ByteBuffer src,
    -                                             CharBuffer dst)
    -        {
    -            int mark = src.position();
    -            int b1 = 0, b2 = 0, b3 = 0;
    -
    -            try {
    -                while (src.hasRemaining()) {
    -                    b1 = src.get();
    -                    int inputSize = 1;
    -                    switch (b1) {
    -                        case ISO_SO:
    -                            shiftout = true;
    -                            break;
    -                        case ISO_SI:
    -                            shiftout = false;
    -                            break;
    -                        case ISO_ESC:
    -                            if (src.remaining() < minDesignatorLength)
    -                                return CoderResult.UNDERFLOW;
    -
    -                            int desig = findDesigBuf(src, SODesig);
    -                            if (desig != -1) {
    -                                curSODes = desig;
    -                                inputSize = SODesig[desig].length + 1;
    -                                break;
    -                            }
    -                            desig = findDesigBuf(src, SS2Desig);
    -                            if (desig != -1) {
    -                                curSS2Des = desig;
    -                                inputSize = SS2Desig[desig].length + 1;
    -                                break;
    -                            }
    -                            desig = findDesigBuf(src, SS3Desig);
    -                            if (desig != -1) {
    -                                curSS3Des = desig;
    -                                inputSize = SS3Desig[desig].length + 1;
    -                                break;
    -                            }
    -
    -                            if (src.remaining() < 1)
    -                                return CoderResult.UNDERFLOW;
    -                            b1 = src.get();
    -                            switch(b1) {
    -                                case ISO_SS2_7:
    -                                    if (src.remaining() < 2)
    -                                        return CoderResult.UNDERFLOW;
    -                                    b2 = src.get();
    -                                    b3 = src.get();
    -                                    if (dst.remaining() < 1)
    -                                        return CoderResult.OVERFLOW;
    -                                    dst.put(decode((byte)b2,
    -                                                   (byte)b3,
    -                                                   SS2Flag));
    -                                    inputSize = 4;
    -                                    break;
    -                                case ISO_SS3_7:
    -                                    if (src.remaining() < 2)
    -                                        return CoderResult.UNDERFLOW;
    -                                    b2 = src.get();
    -                                    b3 = src.get();
    -                                    if (dst.remaining() < 1)
    -                                        return CoderResult.OVERFLOW;
    -                                    dst.put(decode((byte)b2,
    -                                                   (byte)b3,
    -                                                   SS3Flag));
    -                                    inputSize = 4;
    -                                    break;
    -                                default:
    -                                    return CoderResult.malformedForLength(2);
    -                            }
    -                            break;
    -                        default:
    -                            if (dst.remaining() < 1)
    -                                return CoderResult.OVERFLOW;
    -                            if (!shiftout) {
    -                                dst.put((char)(b1 & 0xff));
    -                            } else {
    -                                if (dst.remaining() < 1)
    -                                    return CoderResult.OVERFLOW;
    -                                if (src.remaining() < 1)
    -                                    return CoderResult.UNDERFLOW;
    -                                b2 = src.get() & 0xff;
    -                                dst.put(decode((byte)b1,
    -                                                      (byte)b2,
    -                                                        SOFlag));
    -                                inputSize = 2;
    -                            }
    -                            break;
    -                    }
    -                    mark += inputSize;
    -                }
    -                return CoderResult.UNDERFLOW;
    -            } catch (Exception e) { e.printStackTrace(); return CoderResult.OVERFLOW; }
    -            finally {
    -                src.position(mark);
    -            }
    -        }
    +    protected static class Encoder extends CharsetEncoder {
     
    -        protected CoderResult decodeLoop(ByteBuffer src,
    -                                         CharBuffer dst)
    -        {
    -            if (src.hasArray() && dst.hasArray())
    -                return decodeArrayLoop(src, dst);
    -            else
    -                return decodeBufferLoop(src, dst);
    -        }
    -    }
    +        private static final byte ISO_ESC = 0x1b;
    +        private static final byte ISO_SI = 0x0f;
    +        private static final byte ISO_SO = 0x0e;
    +        private static final byte ISO_SS2_7 = 0x4e;
    +        private static final byte ISO_SS3_7 = 0x4f;
     
    -    protected static class Encoder extends CharsetEncoder {
             private final Surrogate.Parser sgp = new Surrogate.Parser();
             public static final byte SS2 = (byte)0x8e;
             public static final byte PLANE2 = (byte)0xA2;
             public static final byte PLANE3 = (byte)0xA3;
    -        private final byte MSB = (byte)0x80;
     
             protected final byte maximumDesignatorLength = 4;
     
    @@ -428,9 +102,9 @@ protected void implReset() {
     
             private int unicodeToNative(char unicode, byte ebyte[]) {
                 int index = 0;
    -            char        convChar[] = {unicode};
    -            byte        convByte[] = new byte[4];
    -            int         converted;
    +            char[] convChar = {unicode};
    +            byte[] convByte = new byte[4];
    +            int converted;
     
                 try{
                     CharBuffer cc = CharBuffer.wrap(convChar);
    @@ -491,16 +165,13 @@ private CoderResult encodeArrayLoop(CharBuffer src,
                 char[] sa = src.array();
                 int sp = src.arrayOffset() + src.position();
                 int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
    +
                 byte[] da = dst.array();
                 int dp = dst.arrayOffset() + dst.position();
                 int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
     
    -            int outputSize = 0;
    -            byte[]  outputByte = new byte[8];
    +            int outputSize;
    +            byte[] outputByte = new byte[8];
                 newshiftout = shiftout;
                 newSODesDefined = SODesDefined;
                 newSS2DesDefined = SS2DesDefined;
    @@ -557,9 +228,8 @@ private CoderResult encodeArrayLoop(CharBuffer src,
             private CoderResult encodeBufferLoop(CharBuffer src,
                                                  ByteBuffer dst)
             {
    -            int outputSize = 0;
    -            byte[]  outputByte = new byte[8];
    -            int     inputSize = 0;                 // Size of input
    +            int outputSize;
    +            byte[] outputByte = new byte[8];
                 newshiftout = shiftout;
                 newSODesDefined = SODesDefined;
                 newSS2DesDefined = SS2DesDefined;
    @@ -584,7 +254,7 @@ private CoderResult encodeBufferLoop(CharBuffer src,
                                 outputSize = 1;
                                 outputByte[0] = (byte)(inputChar & 0x7f);
                             }
    -                        if(inputChar == '\n'){
    +                        if (inputChar == '\n') {
                                 newSODesDefined = false;
                                 newSS2DesDefined = false;
                                 newSS3DesDefined = false;
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_CN.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_CN.java
    index 4041522754d..a026158d12d 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_CN.java
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_CN.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -34,7 +34,6 @@
     import java.nio.charset.CharsetDecoder;
     import java.nio.charset.CharsetEncoder;
     import java.nio.charset.CoderResult;
    -import java.nio.charset.CharacterCodingException;
     import sun.nio.cs.DoubleByte;
     import sun.nio.cs.HistoricallyNamedCharset;
     import sun.nio.cs.US_ASCII;
    @@ -86,17 +85,13 @@ static class Decoder extends CharsetDecoder {
             private boolean shiftOut;
             private byte currentSODesig;
     
    -        private static final Charset gb2312 = new EUC_CN();
    -        private static final Charset cns = new EUC_TW();
    -        private final DoubleByte.Decoder gb2312Decoder;
    -        private final EUC_TW.Decoder cnsDecoder;
    +        private static final DoubleByte.Decoder GB2312 =
    +                (DoubleByte.Decoder)new EUC_CN().newDecoder();
     
             Decoder(Charset cs) {
                 super(cs, 1.0f, 1.0f);
                 shiftOut = false;
                 currentSODesig = SODesigGB;
    -            gb2312Decoder = (DoubleByte.Decoder)gb2312.newDecoder();
    -            cnsDecoder = (EUC_TW.Decoder)cns.newDecoder();
             }
     
             protected void implReset() {
    @@ -107,34 +102,30 @@ protected void implReset() {
             private char cnsDecode(byte byte1, byte byte2, byte SS) {
                 byte1 |= MSB;
                 byte2 |= MSB;
    -            int p = 0;
    +            int p;
                 if (SS == ISO_SS2_7)
                     p = 1;    //plane 2, index -- 1
                 else if (SS == ISO_SS3_7)
                     p = 2;    //plane 3, index -- 2
                 else
                     return REPLACE_CHAR;  //never happen.
    -            char[] ret = cnsDecoder.toUnicode(byte1 & 0xff,
    -                                              byte2 & 0xff,
    -                                              p);
    -            if (ret == null || ret.length == 2)
    -                return REPLACE_CHAR;
    -            return ret[0];
    +            return EUC_TW.Decoder.decodeSingleOrReplace(byte1 & 0xff,
    +                                                        byte2 & 0xff,
    +                                                        p,
    +                                                        REPLACE_CHAR);
             }
     
             private char SODecode(byte byte1, byte byte2, byte SOD) {
                 byte1 |= MSB;
                 byte2 |= MSB;
                 if (SOD == SODesigGB) {
    -                return gb2312Decoder.decodeDouble(byte1 & 0xff,
    -                                                  byte2 & 0xff);
    +                return GB2312.decodeDouble(byte1 & 0xff,
    +                                           byte2 & 0xff);
                 } else {    // SOD == SODesigCNS
    -                char[] ret = cnsDecoder.toUnicode(byte1 & 0xff,
    -                                                  byte2 & 0xff,
    -                                                  0);
    -                if (ret == null)
    -                    return REPLACE_CHAR;
    -                return ret[0];
    +                return EUC_TW.Decoder.decodeSingleOrReplace(byte1 & 0xff,
    +                                                            byte2 & 0xff,
    +                                                            0,
    +                                                            REPLACE_CHAR);
                 }
             }
     
    @@ -142,9 +133,9 @@ private CoderResult decodeBufferLoop(ByteBuffer src,
                                                  CharBuffer dst)
             {
                 int mark = src.position();
    -            byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
    -            int inputSize = 0;
    -            char c = REPLACE_CHAR;
    +            byte b1, b2, b3, b4;
    +            int inputSize;
    +            char c;
                 try {
                     while (src.hasRemaining()) {
                         b1 = src.get();
    @@ -264,21 +255,17 @@ private CoderResult decodeBufferLoop(ByteBuffer src,
             private CoderResult decodeArrayLoop(ByteBuffer src,
                                                 CharBuffer dst)
             {
    -            int inputSize = 0;
    -            byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
    -            char c = REPLACE_CHAR;
    +            int inputSize;
    +            byte b1, b2, b3, b4;
    +            char c;
     
                 byte[] sa = src.array();
                 int sp = src.arrayOffset() + src.position();
                 int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
     
                 char[] da = dst.array();
                 int dp = dst.arrayOffset() + dst.position();
                 int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
     
                 try {
                     while (sp < sl) {
    @@ -306,7 +293,7 @@ private CoderResult decodeArrayLoop(ByteBuffer src,
     
                                     if ((b3 & (byte)0x80) != 0)
                                         return CoderResult.malformedForLength(inputSize);
    -                                if (b3 == 'A'){              // "$A"
    +                                if (b3 == 'A') {              // "$A"
                                         /* $A is not a legal designator sequence for
                                            ISO2022_CN, it is listed as an escape sequence
                                            for GB2312 in ISO2022-JP-2. Keep it here just for
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_CN_CNS.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_CN_CNS.java
    index af623c6c009..3021f195ea5 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_CN_CNS.java
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_CN_CNS.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -29,11 +29,8 @@
     package sun.nio.cs.ext;
     
     import java.nio.charset.Charset;
    -import java.nio.ByteBuffer;
    -import java.nio.CharBuffer;
     import java.nio.charset.CharsetDecoder;
     import java.nio.charset.CharsetEncoder;
    -import java.nio.charset.CoderResult;
     import sun.nio.cs.HistoricallyNamedCharset;
     import sun.nio.cs.*;
     
    @@ -64,22 +61,24 @@ public CharsetEncoder newEncoder() {
     
         private static class Encoder extends ISO2022.Encoder {
     
    +        private static final Charset cns = new EUC_TW();
    +
    +        private static final byte[] SOD = new byte[] {'$', ')', 'G' };
    +        private static final byte[] SS2D = new byte[] {'$', '*', 'H' };
    +        private static final byte[] SS3D = new byte[] {'$', '+', 'I' };
    +
             public Encoder(Charset cs)
             {
                 super(cs);
    -            SODesig =  new byte[] {'$', ')', 'G' };
    -            SS2Desig = new byte[] {'$', '*', 'H' };
    -            SS3Desig = new byte[] {'$', '+', 'I' };
    -
    -            try {
    -                Charset cset = Charset.forName("EUC_TW"); // CNS11643
    -                ISOEncoder = cset.newEncoder();
    -            } catch (Exception e) { }
    +            SODesig = SOD;
    +            SS2Desig = SS2D;
    +            SS3Desig = SS3D;
    +            ISOEncoder = cns.newEncoder();
             }
     
    -        private byte[] bb = new byte[4];
    +        private final byte[] bb = new byte[4];
             public boolean canEncode(char c) {
    -            int n = 0;
    +            int n;
                 return (c <= '\u007f' ||
                         (n = ((EUC_TW.Encoder)ISOEncoder).toEUC(c, bb)) == 2 ||
                         (n == 4 && bb[0] == SS2 &&
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_CN_GB.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_CN_GB.java
    index aca60b5f255..5c53440482d 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_CN_GB.java
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_CN_GB.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -29,11 +29,8 @@
     package sun.nio.cs.ext;
     
     import java.nio.charset.Charset;
    -import java.nio.ByteBuffer;
    -import java.nio.CharBuffer;
     import java.nio.charset.CharsetDecoder;
     import java.nio.charset.CharsetEncoder;
    -import java.nio.charset.CoderResult;
     import sun.nio.cs.*;
     import sun.nio.cs.HistoricallyNamedCharset;
     
    @@ -65,15 +62,15 @@ public CharsetEncoder newEncoder() {
     
         private static class Encoder extends ISO2022.Encoder {
     
    +        private static final Charset gb2312 = new EUC_CN();
    +
    +        private static final byte[] SOD = new byte[] {'$', ')', 'A' };
    +
             public Encoder(Charset cs)
             {
                 super(cs);
    -            SODesig = new byte[] { '$', ')', 'A'};
    -
    -            try {
    -                Charset cset = Charset.forName("EUC_CN"); // GB2312
    -                ISOEncoder = cset.newEncoder();
    -            } catch (Exception e) { }
    +            SODesig = SOD;
    +            ISOEncoder = gb2312.newEncoder();
             }
     
             /*
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_JP.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_JP.java
    index 797df1b4c38..dba95f20981 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_JP.java
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_JP.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -172,14 +172,14 @@ protected boolean doSBKANA() {
         static class Decoder extends CharsetDecoder
             implements DelegatableDecoder {
     
    -        final static DoubleByte.Decoder DEC0208 =
    +        static final DoubleByte.Decoder DEC0208 =
                 (DoubleByte.Decoder)new JIS_X_0208().newDecoder();
     
             private int currentState;
             private int previousState;
     
    -        private DoubleByte.Decoder dec0208;
    -        private DoubleByte.Decoder dec0212;
    +        private final DoubleByte.Decoder dec0208;
    +        private final DoubleByte.Decoder dec0212;
     
             private Decoder(Charset cs) {
                 this(cs, DEC0208, null);
    @@ -203,20 +203,16 @@ public void implReset() {
             private CoderResult decodeArrayLoop(ByteBuffer src,
                                                 CharBuffer dst)
             {
    -            int inputSize = 0;
    -            int b1 = 0, b2 = 0, b3 = 0, b4 = 0;
    -            char c = UNMAPPABLE_DECODING;
    +            int inputSize;
    +            int b1, b2, b3, b4;
    +            char c;
                 byte[] sa = src.array();
                 int sp = src.arrayOffset() + src.position();
                 int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
     
                 char[] da = dst.array();
                 int dp = dst.arrayOffset() + dst.position();
                 int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
     
                 try {
                     while (sp < sl) {
    @@ -331,8 +327,8 @@ private CoderResult decodeBufferLoop(ByteBuffer src,
                                                  CharBuffer dst)
             {
                 int mark = src.position();
    -            int b1 = 0, b2 = 0, b3 = 0, b4=0;
    -            char c = UNMAPPABLE_DECODING;
    +            int b1, b2, b3, b4;
    +            char c;
                 int inputSize = 0;
                 try {
                     while (src.hasRemaining()) {
    @@ -465,12 +461,12 @@ static class Encoder extends CharsetEncoder {
             final static DoubleByte.Encoder ENC0208 =
                 (DoubleByte.Encoder)new JIS_X_0208().newEncoder();
     
    -        private static byte[] repl = { (byte)0x21, (byte)0x29 };
    +        private static final byte[] repl = { (byte)0x21, (byte)0x29 };
             private int currentMode = ASCII;
             private int replaceMode = JISX0208_1983;
    -        private DoubleByte.Encoder enc0208;
    -        private DoubleByte.Encoder enc0212;
    -        private boolean doSBKANA;
    +        private final DoubleByte.Encoder enc0208;
    +        private final DoubleByte.Encoder enc0212;
    +        private final boolean doSBKANA;
     
             private Encoder(Charset cs) {
                 this(cs, ENC0208, null, true);
    @@ -535,13 +531,10 @@ private CoderResult encodeArrayLoop(CharBuffer src,
                 char[] sa = src.array();
                 int sp = src.arrayOffset() + src.position();
                 int sl = src.arrayOffset() + src.limit();
    -            assert (sp <= sl);
    -            sp = (sp <= sl ? sp : sl);
    +
                 byte[] da = dst.array();
                 int dp = dst.arrayOffset() + dst.position();
                 int dl = dst.arrayOffset() + dst.limit();
    -            assert (dp <= dl);
    -            dp = (dp <= dl ? dp : dl);
     
                 try {
                     while (sp < sl) {
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_KR.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_KR.java
    index 9ee19cbf996..7145328a2ba 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_KR.java
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/ISO2022_KR.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -40,11 +40,12 @@
     public class ISO2022_KR extends ISO2022
     implements HistoricallyNamedCharset
     {
    -    private static Charset ksc5601_cs;
    +    private static class Holder {
    +        private static final Charset ksc5601_cs = new EUC_KR();
    +    }
     
         public ISO2022_KR() {
             super("ISO-2022-KR", ExtendedCharsets.aliasesFor("ISO-2022-KR"));
    -        ksc5601_cs = new EUC_KR();
         }
     
         public boolean contains(Charset cs) {
    @@ -66,26 +67,263 @@ public CharsetEncoder newEncoder() {
             return new Encoder(this);
         }
     
    -    private static class Decoder extends ISO2022.Decoder {
    -        public Decoder(Charset cs)
    +
    +    private static class Decoder extends CharsetDecoder {
    +
    +        private static final byte[] SOD = new byte[] {'$', ')', 'C' };
    +
    +        private static final DoubleByte.Decoder KSC5601 = (DoubleByte.Decoder)
    +                new EUC_KR().newDecoder();
    +
    +        private static final byte ISO_ESC = 0x1b;
    +        private static final byte ISO_SI = 0x0f;
    +        private static final byte ISO_SO = 0x0e;
    +        private static final byte ISO_SS2_7 = 0x4e;
    +        private static final byte ISO_SS3_7 = 0x4f;
    +        private static final byte MSB = (byte)0x80;
    +        private static final char REPLACE_CHAR = '\uFFFD';
    +        private static final byte minDesignatorLength = 3;
    +
    +        private static final byte SOFlag = 0;
    +        private static final byte SS2Flag = 1;
    +        private static final byte SS3Flag = 2;
    +
    +        private boolean shiftout;
    +
    +        private Decoder(Charset cs) {
    +            super(cs, 1.0f, 1.0f);
    +        }
    +
    +        protected void implReset() {
    +            shiftout = false;
    +        }
    +
    +        private char decode(byte byte1, byte byte2, byte shiftFlag)
             {
    -            super(cs);
    -            SODesig = new byte[][] {{(byte)'$', (byte)')', (byte)'C'}};
    -            SODecoder = new CharsetDecoder[1];
    +            if (shiftFlag == SOFlag) {
    +                return KSC5601.decodeDouble((byte1 | MSB) & 0xFF, (byte2 | MSB) & 0xFF);
    +            }
    +            return REPLACE_CHAR;
    +        }
    +
    +        private boolean findDesig(byte[] in, int sp, int sl) {
    +            if (sl - sp >= SOD.length) {
    +                int j = 0;
    +                while (j < SOD.length && in[sp + j] == SOD[j]) { j++; }
    +                return j == SOD.length;
    +            }
    +            return false;
    +        }
    +
    +        private boolean findDesigBuf(ByteBuffer in) {
    +            if (in.remaining() >= SOD.length) {
    +                int j = 0;
    +                in.mark();
    +                while (j < SOD.length && in.get() == SOD[j]) { j++; }
    +                if (j == SOD.length)
    +                    return true;
    +                in.reset();
    +            }
    +            return false;
    +        }
    +
    +        private CoderResult decodeArrayLoop(ByteBuffer src,
    +                                            CharBuffer dst)
    +        {
    +            byte[] sa = src.array();
    +            int sp = src.arrayOffset() + src.position();
    +            int sl = src.arrayOffset() + src.limit();
    +
    +            char[] da = dst.array();
    +            int dp = dst.arrayOffset() + dst.position();
    +            int dl = dst.arrayOffset() + dst.limit();
    +
    +            int b1, b2, b3;
     
                 try {
    -                SODecoder[0] = ksc5601_cs.newDecoder();
    -            } catch (Exception e) {};
    +                while (sp < sl) {
    +                    b1 = sa[sp] & 0xff;
    +                    int inputSize = 1;
    +                    switch (b1) {
    +                        case ISO_SO:
    +                            shiftout = true;
    +                            inputSize = 1;
    +                            break;
    +                        case ISO_SI:
    +                            shiftout = false;
    +                            inputSize = 1;
    +                            break;
    +                        case ISO_ESC:
    +                            if (sl - sp - 1 < minDesignatorLength)
    +                                return CoderResult.UNDERFLOW;
    +
    +                            if (findDesig(sa, sp + 1, sl)) {
    +                                inputSize = SOD.length + 1;
    +                                break;
    +                            }
    +                            if (sl - sp < 2)
    +                                return CoderResult.UNDERFLOW;
    +                            b1 = sa[sp + 1];
    +                            switch (b1) {
    +                                case ISO_SS2_7:
    +                                    if (sl - sp < 4)
    +                                        return CoderResult.UNDERFLOW;
    +                                    b2 = sa[sp +2];
    +                                    b3 = sa[sp +3];
    +                                    if (dl - dp <1)
    +                                        return CoderResult.OVERFLOW;
    +                                    da[dp] = decode((byte)b2,
    +                                            (byte)b3,
    +                                            SS2Flag);
    +                                    dp++;
    +                                    inputSize = 4;
    +                                    break;
    +                                case ISO_SS3_7:
    +                                    if (sl - sp < 4)
    +                                        return CoderResult.UNDERFLOW;
    +                                    b2 = sa[sp + 2];
    +                                    b3 = sa[sp + 3];
    +                                    if (dl - dp < 1)
    +                                        return CoderResult.OVERFLOW;
    +                                    da[dp] = decode((byte)b2,
    +                                            (byte)b3,
    +                                            SS3Flag);
    +                                    dp++;
    +                                    inputSize = 4;
    +                                    break;
    +                                default:
    +                                    return CoderResult.malformedForLength(2);
    +                            }
    +                            break;
    +                        default:
    +                            if (dl - dp < 1)
    +                                return CoderResult.OVERFLOW;
    +                            if (!shiftout) {
    +                                da[dp++]=(char)(sa[sp] & 0xff);
    +                            } else {
    +                                if (dl - dp < 1)
    +                                    return CoderResult.OVERFLOW;
    +                                if (sl - sp < 2)
    +                                    return CoderResult.UNDERFLOW;
    +                                b2 = sa[sp+1] & 0xff;
    +                                da[dp++] = decode((byte)b1,
    +                                        (byte)b2,
    +                                        SOFlag);
    +                                inputSize = 2;
    +                            }
    +                            break;
    +                    }
    +                    sp += inputSize;
    +                }
    +                return CoderResult.UNDERFLOW;
    +            } finally {
    +                src.position(sp - src.arrayOffset());
    +                dst.position(dp - dst.arrayOffset());
    +            }
    +        }
    +
    +        private CoderResult decodeBufferLoop(ByteBuffer src,
    +                                             CharBuffer dst)
    +        {
    +            int mark = src.position();
    +            int b1, b2, b3;
    +
    +            try {
    +                while (src.hasRemaining()) {
    +                    b1 = src.get();
    +                    int inputSize = 1;
    +                    switch (b1) {
    +                        case ISO_SO:
    +                            shiftout = true;
    +                            break;
    +                        case ISO_SI:
    +                            shiftout = false;
    +                            break;
    +                        case ISO_ESC:
    +                            if (src.remaining() < minDesignatorLength)
    +                                return CoderResult.UNDERFLOW;
    +
    +                            if (findDesigBuf(src)) {
    +                                inputSize = SOD.length + 1;
    +                                break;
    +                            }
    +
    +                            if (src.remaining() < 1)
    +                                return CoderResult.UNDERFLOW;
    +                            b1 = src.get();
    +                            switch(b1) {
    +                                case ISO_SS2_7:
    +                                    if (src.remaining() < 2)
    +                                        return CoderResult.UNDERFLOW;
    +                                    b2 = src.get();
    +                                    b3 = src.get();
    +                                    if (dst.remaining() < 1)
    +                                        return CoderResult.OVERFLOW;
    +                                    dst.put(decode((byte)b2,
    +                                            (byte)b3,
    +                                            SS2Flag));
    +                                    inputSize = 4;
    +                                    break;
    +                                case ISO_SS3_7:
    +                                    if (src.remaining() < 2)
    +                                        return CoderResult.UNDERFLOW;
    +                                    b2 = src.get();
    +                                    b3 = src.get();
    +                                    if (dst.remaining() < 1)
    +                                        return CoderResult.OVERFLOW;
    +                                    dst.put(decode((byte)b2,
    +                                            (byte)b3,
    +                                            SS3Flag));
    +                                    inputSize = 4;
    +                                    break;
    +                                default:
    +                                    return CoderResult.malformedForLength(2);
    +                            }
    +                            break;
    +                        default:
    +                            if (dst.remaining() < 1)
    +                                return CoderResult.OVERFLOW;
    +                            if (!shiftout) {
    +                                dst.put((char)(b1 & 0xff));
    +                            } else {
    +                                if (src.remaining() < 1)
    +                                    return CoderResult.UNDERFLOW;
    +                                b2 = src.get() & 0xff;
    +                                dst.put(decode((byte)b1,
    +                                        (byte)b2,
    +                                        SOFlag));
    +                                inputSize = 2;
    +                            }
    +                            break;
    +                    }
    +                    mark += inputSize;
    +                }
    +                return CoderResult.UNDERFLOW;
    +            } catch (Exception e) { e.printStackTrace(); return CoderResult.OVERFLOW; }
    +            finally {
    +                src.position(mark);
    +            }
    +        }
    +
    +        protected CoderResult decodeLoop(ByteBuffer src,
    +                                         CharBuffer dst)
    +        {
    +            if (src.hasArray() && dst.hasArray())
    +                return decodeArrayLoop(src, dst);
    +            else
    +                return decodeBufferLoop(src, dst);
             }
         }
     
         private static class Encoder extends ISO2022.Encoder {
     
    +        private static final byte[] SOD = new byte[] {'$', ')', 'C' };
    +
             public Encoder(Charset cs) {
                 super(cs);
    -            SODesig = new byte[] {'$', ')', 'C' };
    +            SODesig = SOD;
                 try {
    -                ISOEncoder = ksc5601_cs.newEncoder();
    +                ISOEncoder = Holder.ksc5601_cs.newEncoder();
                 } catch (Exception e) { }
             }
     
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS50220.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS50220.java
    index 2b18f7d419d..16cb9866ce7 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS50220.java
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS50220.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -53,24 +53,26 @@ public boolean contains(Charset cs) {
         }
     
         public CharsetDecoder newDecoder() {
    -        return new Decoder(this, DEC0208, DEC0212);
    +        return new Decoder(this, Holder.DEC0208, Holder.DEC0212);
         }
     
         public CharsetEncoder newEncoder() {
    -        return new Encoder(this, ENC0208, ENC0212, doSBKANA());
    +        return new Encoder(this, Holder.ENC0208, Holder.ENC0212, doSBKANA());
         }
     
    -    private final static DoubleByte.Decoder DEC0208 =
    -        (DoubleByte.Decoder)new JIS_X_0208_MS5022X().newDecoder();
    +    private static class Holder {
    +        private static final DoubleByte.Decoder DEC0208 =
    +                (DoubleByte.Decoder) new JIS_X_0208_MS5022X().newDecoder();
     
    -    private final static DoubleByte.Decoder DEC0212 =
    -        (DoubleByte.Decoder)new JIS_X_0212_MS5022X().newDecoder();
    +        private static final DoubleByte.Decoder DEC0212 =
    +                (DoubleByte.Decoder) new JIS_X_0212_MS5022X().newDecoder();
     
    -    private final static DoubleByte.Encoder ENC0208 =
    -        (DoubleByte.Encoder)new JIS_X_0208_MS5022X().newEncoder();
    +        private static final DoubleByte.Encoder ENC0208 =
    +                (DoubleByte.Encoder) new JIS_X_0208_MS5022X().newEncoder();
     
    -    private final static DoubleByte.Encoder ENC0212 =
    -        (DoubleByte.Encoder)new JIS_X_0212_MS5022X().newEncoder();
    +        private static final DoubleByte.Encoder ENC0212 =
    +                (DoubleByte.Encoder) new JIS_X_0212_MS5022X().newEncoder();
    +    }
     
         protected boolean doSBKANA() {
             return false;
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS932_0213.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS932_0213.java
    index b445cd59c07..5fbadc5d580 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS932_0213.java
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS932_0213.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -52,7 +52,7 @@ public CharsetEncoder newEncoder() {
         }
     
         protected static class Decoder extends SJIS_0213.Decoder {
    -        static DoubleByte.Decoder decMS932 =
    +        static final DoubleByte.Decoder decMS932 =
                 (DoubleByte.Decoder)new MS932().newDecoder();
             protected Decoder(Charset cs) {
                 super(cs);
    @@ -68,7 +68,7 @@ protected char decodeDouble(int b1, int b2) {
     
         protected static class Encoder extends SJIS_0213.Encoder {
             // we only use its encodeChar() method
    -        static DoubleByte.Encoder encMS932 =
    +        static final DoubleByte.Encoder encMS932 =
                 (DoubleByte.Encoder)new MS932().newEncoder();
             protected Encoder(Charset cs) {
                 super(cs);
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS950_HKSCS.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS950_HKSCS.java.template
    index 641c8e6bead..aeb9822faa7 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS950_HKSCS.java.template
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS950_HKSCS.java.template
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -60,8 +60,8 @@ public class MS950_HKSCS extends Charset implements HistoricallyNamedCharset
             private static DoubleByte.Decoder ms950 =
                 (DoubleByte.Decoder)new MS950().newDecoder();
     
    -        private static char[][] b2cBmp = new char[0x100][];
    -        private static char[][] b2cSupp = new char[0x100][];
    +        private static final char[][] b2cBmp = new char[0x100][];
    +        private static final char[][] b2cSupp = new char[0x100][];
             static {
                 initb2c(b2cBmp, HKSCSMapping.b2cBmpStr);
                 initb2c(b2cSupp, HKSCSMapping.b2cSuppStr);
    @@ -76,8 +76,8 @@ public class MS950_HKSCS extends Charset implements HistoricallyNamedCharset
             private static DoubleByte.Encoder ms950 =
                 (DoubleByte.Encoder)new MS950().newEncoder();
     
    -        static char[][] c2bBmp = new char[0x100][];
    -        static char[][] c2bSupp = new char[0x100][];
    +        static final char[][] c2bBmp = new char[0x100][];
    +        static final char[][] c2bSupp = new char[0x100][];
             static {
                 initc2b(c2bBmp, HKSCSMapping.b2cBmpStr, HKSCSMapping.pua);
                 initc2b(c2bSupp, HKSCSMapping.b2cSuppStr, null);
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS950_HKSCS_XP.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS950_HKSCS_XP.java.template
    index bc009b0a264..41a26f561e6 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS950_HKSCS_XP.java.template
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/MS950_HKSCS_XP.java.template
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -65,7 +65,7 @@ public class MS950_HKSCS_XP extends Charset
              * MS HKSCS mappings which maps 0x8BC2 --> U+5C22
              * a character defined with the Unified CJK block
              */
    -        private static char[][] b2cBmp = new char[0x100][];
    +        private static final char[][] b2cBmp = new char[0x100][];
             static {
                 initb2c(b2cBmp, HKSCS_XPMapping.b2cBmpStr);
             }
    @@ -88,7 +88,7 @@ public class MS950_HKSCS_XP extends Charset
              * Published MS HKSCS mappings show
              * U+5C22 <--> 0x8BC2
              */
    -        static char[][] c2bBmp = new char[0x100][];
    +        static final char[][] c2bBmp = new char[0x100][];
             static {
                 initc2b(c2bBmp, HKSCS_XPMapping.b2cBmpStr, null);
             }
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/MSISO2022JP.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/MSISO2022JP.java
    index 0949960775d..d75354abfd9 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/MSISO2022JP.java
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/MSISO2022JP.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -55,9 +55,9 @@ public CharsetEncoder newEncoder() {
         }
     
         private static class CoderHolder {
    -        final static DoubleByte.Decoder DEC0208 =
    +        static final DoubleByte.Decoder DEC0208 =
                 (DoubleByte.Decoder)new JIS_X_0208_MS932().newDecoder();
    -        final static DoubleByte.Encoder ENC0208 =
    +        static final DoubleByte.Encoder ENC0208 =
                 (DoubleByte.Encoder)new JIS_X_0208_MS932().newEncoder();
         }
     }
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/SJIS_0213.java b/src/jdk.charsets/share/classes/sun/nio/cs/ext/SJIS_0213.java
    index 85657830847..0d16040c91a 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/SJIS_0213.java
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/SJIS_0213.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -76,12 +76,14 @@ public CharsetEncoder newEncoder() {
             return new Encoder(this);
         }
     
    -    static CharsetMapping mapping = AccessController.doPrivileged(
    -        new PrivilegedAction() {
    -            public CharsetMapping run() {
    -                return CharsetMapping.get(SJIS_0213.class.getResourceAsStream("sjis0213.dat"));
    -            }
    -        });
    +    private static class Holder {
    +        static final CharsetMapping mapping = AccessController.doPrivileged(
    +                new PrivilegedAction() {
    +                    public CharsetMapping run() {
    +                        return CharsetMapping.get(SJIS_0213.class.getResourceAsStream("sjis0213.dat"));
    +                    }
    +                });
    +    }
     
         protected static class Decoder extends CharsetDecoder {
             protected static final char UNMAPPABLE = CharsetMapping.UNMAPPABLE_DECODING;
    @@ -188,21 +190,21 @@ protected CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
             }
     
             protected char decodeSingle(int b) {
    -            return mapping.decodeSingle(b);
    +            return Holder.mapping.decodeSingle(b);
             }
     
             protected char decodeDouble(int b1, int b2) {
    -            return mapping.decodeDouble(b1, b2);
    +            return Holder.mapping.decodeDouble(b1, b2);
             }
     
             private char[] cc = new char[2];
             private CharsetMapping.Entry comp = new CharsetMapping.Entry();
             protected char[] decodeDoubleEx(int b1, int b2) {
                 int db = (b1 << 8) | b2;
    -            if (mapping.decodeSurrogate(db, cc) != null)
    +            if (Holder.mapping.decodeSurrogate(db, cc) != null)
                     return cc;
                 comp.bs = db;
    -            if (mapping.decodeComposite(comp, cc) != null)
    +            if (Holder.mapping.decodeComposite(comp, cc) != null)
                     return cc;
                 return null;
             }
    @@ -221,23 +223,23 @@ public boolean canEncode(char c) {
             }
     
             protected int encodeChar(char ch) {
    -            return mapping.encodeChar(ch);
    +            return Holder.mapping.encodeChar(ch);
             }
     
             protected int encodeSurrogate(char hi, char lo) {
    -            return mapping.encodeSurrogate(hi, lo);
    +            return Holder.mapping.encodeSurrogate(hi, lo);
             }
     
             private CharsetMapping.Entry comp = new CharsetMapping.Entry();
             protected int encodeComposite(char base, char cc) {
                 comp.cp = base;
                 comp.cp2 = cc;
    -            return mapping.encodeComposite(comp);
    +            return Holder.mapping.encodeComposite(comp);
             }
     
             protected boolean isCompositeBase(char ch) {
                 comp.cp = ch;
    -            return mapping.isCompositeBase(comp);
    +            return Holder.mapping.isCompositeBase(comp);
             }
     
             // Unlike surrogate pair, the base character of a base+cc composite
    diff --git a/src/jdk.charsets/share/classes/sun/nio/cs/ext/SimpleEUCEncoder.java.template b/src/jdk.charsets/share/classes/sun/nio/cs/ext/SimpleEUCEncoder.java.template
    index 25ef479bd01..0811087cd21 100644
    --- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/SimpleEUCEncoder.java.template
    +++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/SimpleEUCEncoder.java.template
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -98,13 +98,10 @@ public abstract class SimpleEUCEncoder
             char[] sa = src.array();
             int sp = src.arrayOffset() + src.position();
             int sl = src.arrayOffset() + src.limit();
    -        assert (sp <= sl);
    -        sp = (sp <= sl ? sp : sl);
    +
             byte[] da = dst.array();
             int dp = dst.arrayOffset() + dst.position();
             int dl = dst.arrayOffset() + dst.limit();
    -        assert (dp <= dl);
    -        dp = (dp <= dl ? dp : dl);
     
             int     index;
             int     spaceNeeded;
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
    index f9b75f8d657..709ac23b47e 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java
    @@ -386,8 +386,8 @@ void fillIn(ClassSymbol c) {
                     throw cf;
                 } finally {
                     currentClassFile = previousClassFile;
    -                if (c.isValue() && c.projection != null) {
    -                    c.projection.flags_field = (c.flags_field & ~(VALUE | UNATTRIBUTED | FINAL)) | SEALED;
    +                if (c.isPrimitiveClass() && c.projection != null) {
    +                    c.projection.flags_field = (c.flags_field & ~(PRIMITIVE_CLASS | UNATTRIBUTED | FINAL)) | SEALED;
                     }
                 }
             } else {
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
    index 6b2749eed82..f7a3723114e 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
    @@ -98,8 +98,8 @@ public static EnumSet asFlagSet(long flags) {
         /** Added in SE8, represents constructs implicitly declared in source. */
         public static final int MANDATED     = 1<<15;
     
    -    /** Marks a type as a value-type */
    -    public static final int VALUE        = 1<<16;
    +    /** Marks a type as a primitive class */
    +    public static final int PRIMITIVE_CLASS  = 1<<16;
     
         public static final int StandardFlags = 0x0fff;
     
    @@ -110,7 +110,7 @@ public static EnumSet asFlagSet(long flags) {
         public static final int ACC_SUPER    = 0x0020;
         public static final int ACC_BRIDGE   = 0x0040;
         public static final int ACC_VARARGS  = 0x0080;
    -    public static final int ACC_INLINE   = 0x0100;
    +    public static final int ACC_PRIMITIVE = 0x0100;
         public static final int ACC_MODULE   = 0x8000;
     
         /*****************************************
    @@ -405,7 +405,7 @@ public static EnumSet asFlagSet(long flags) {
          */
         public static final int
             AccessFlags                       = PUBLIC | PROTECTED | PRIVATE,
    -        LocalClassFlags                   = FINAL | ABSTRACT | STRICTFP | ENUM | SYNTHETIC  | VALUE,
    +        LocalClassFlags                   = FINAL | ABSTRACT | STRICTFP | ENUM | SYNTHETIC  | PRIMITIVE_CLASS,
             StaticLocalFlags                  = LocalClassFlags | STATIC | INTERFACE,
             MemberClassFlags                  = LocalClassFlags | INTERFACE | AccessFlags,
             MemberStaticClassFlags            = MemberClassFlags | STATIC,
    @@ -420,7 +420,7 @@ public static EnumSet asFlagSet(long flags) {
             RecordMethodFlags                 = AccessFlags | ABSTRACT | STATIC |
                                                 SYNCHRONIZED | FINAL | STRICTFP;
         public static final long
    -        ExtendedStandardFlags             = (long)StandardFlags | DEFAULT | SEALED | NON_SEALED | VALUE,
    +        ExtendedStandardFlags             = (long)StandardFlags | DEFAULT | SEALED | NON_SEALED | PRIMITIVE_CLASS,
             ExtendedMemberClassFlags          = (long)MemberClassFlags | SEALED | NON_SEALED,
             ExtendedMemberStaticClassFlags    = (long) MemberStaticClassFlags | SEALED | NON_SEALED,
             ExtendedClassFlags                = (long)ClassFlags | SEALED | NON_SEALED,
    @@ -451,7 +451,7 @@ public static Set asModifierSet(long flags) {
                 if (0 != (flags & NATIVE))    modifiers.add(Modifier.NATIVE);
                 if (0 != (flags & STRICTFP))  modifiers.add(Modifier.STRICTFP);
                 if (0 != (flags & DEFAULT))   modifiers.add(Modifier.DEFAULT);
    -            if (0 != (flags & VALUE))     modifiers.add(Modifier.VALUE);
    +            if (0 != (flags & PRIMITIVE_CLASS))     modifiers.add(Modifier.PRIMITIVE);
                 modifiers = Collections.unmodifiableSet(modifiers);
                 modifierSets.put(flags, modifiers);
             }
    @@ -498,7 +498,7 @@ public enum Flag {
             BLOCK(Flags.BLOCK),
             ENUM(Flags.ENUM),
             MANDATED(Flags.MANDATED),
    -        INLINE(Flags.VALUE),
    +        PRIMITIVE(Flags.PRIMITIVE_CLASS),
             NOOUTERTHIS(Flags.NOOUTERTHIS),
             EXISTS(Flags.EXISTS),
             COMPOUND(Flags.COMPOUND),
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
    index 7e5a554573d..9a6c26e00bd 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
    @@ -223,7 +223,7 @@ public enum Feature {
             PATTERN_MATCHING_IN_INSTANCEOF(JDK16, Fragments.FeaturePatternMatchingInstanceof, DiagKind.NORMAL),
             REIFIABLE_TYPES_INSTANCEOF(JDK16, Fragments.FeatureReifiableTypesInstanceof, DiagKind.PLURAL),
             RECORDS(JDK16, Fragments.FeatureRecords, DiagKind.PLURAL),
    -        INLINE_TYPES(JDK17, Fragments.FeatureInlineType, DiagKind.NORMAL),
    +        PRIMITIVE_CLASSES(JDK17, Fragments.FeaturePrimitiveClasses, DiagKind.NORMAL),
             SEALED_CLASSES(JDK17, Fragments.FeatureSealedClasses, DiagKind.PLURAL),
             ;
     
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
    index 13e4b03f465..dc417acc1aa 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
    @@ -370,7 +370,7 @@ public Type externalType(Types types) {
             boolean mutateExternalType = false;
             // Computed restricted parameter types
             for (Type pt: t.getParameterTypes()) {
    -            if (pt.isValue()) {
    +            if (pt.isPrimitiveClass()) {
                     mutateExternalType = true;
                     rpt = rpt.append(pt.referenceProjection());
                 } else {
    @@ -378,7 +378,7 @@ public Type externalType(Types types) {
                 }
             }
             Type rt = t.getReturnType();
    -        if (rt.isValue()) {
    +        if (rt.isPrimitiveClass()) {
                 mutateExternalType = true;
                 rrt = rt.referenceProjection();
             } else {
    @@ -441,8 +441,8 @@ public boolean isPrivate() {
             return (flags_field & Flags.AccessFlags) == PRIVATE;
         }
     
    -    public boolean isValue() {
    -        return (flags() & VALUE) != 0;
    +    public boolean isPrimitiveClass() {
    +        return (flags() & PRIMITIVE_CLASS) != 0;
         }
     
         /**
    @@ -1692,7 +1692,7 @@ public boolean isRecord() {
     
             @Override
             public boolean isReferenceProjection() {
    -            return projection != null && projection.isValue();
    +            return projection != null && projection.isPrimitiveClass();
             }
     
             @Override
    @@ -1702,7 +1702,6 @@ public ClassSymbol valueProjection() {
     
             @Override
             public ClassSymbol referenceProjection() {
    -
                 if (projection != null)
                     return projection;
     
    @@ -1717,7 +1716,7 @@ public ClassSymbol referenceProjection() {
                 ct.projection = projectedType;
     
                 Name projectionName = this.name.append('$', this.name.table.names.ref);
    -            long projectionFlags = (this.flags_field & ~(VALUE | UNATTRIBUTED | FINAL)) | SEALED;
    +            long projectionFlags = (this.flags_field & ~(PRIMITIVE_CLASS | UNATTRIBUTED | FINAL)) | SEALED;
     
                 projection = new ClassSymbol(projectionFlags, projectionName, projectedType, this.owner);
                 projection.members_field = WriteableScope.create(projection);
    @@ -1879,14 +1878,14 @@ public void setLazyConstValue(final Env env,
     
             @Override
             public VarSymbol referenceProjection() {
    -            return this.owner.isValue() ?
    +            return this.owner.isPrimitiveClass() ?
                         this.owner.referenceProjection() != null ? projection : null
                                    : null;
             }
     
             @Override
             public VarSymbol valueProjection() {
    -            return  projection != null ? projection.owner.isValue() ? projection : null: null;
    +            return  projection != null ? projection.owner.isPrimitiveClass() ? projection : null: null;
             }
     
             /**
    @@ -2245,10 +2244,10 @@ public boolean overrides(Symbol _other, TypeSymbol origin, Types types, boolean
                 /* If any inline types are involved, ask the same question in the reference universe,
                    where the hierarchy is navigable
                 */
    -            if (origin.isValue())
    +            if (origin.isPrimitiveClass())
                     origin = (TypeSymbol) origin.referenceProjection();
     
    -            if (this.owner.isValue()) {
    +            if (this.owner.isPrimitiveClass()) {
                     return this.projection != null &&
                             this.projection.overrides(_other, origin, types, checkResult, requireConcreteIfInherited);
                 }
    @@ -2311,9 +2310,9 @@ public boolean isInheritedIn(Symbol clazz, Types types) {
                 /* If any inline types are involved, ask the same question in the reference universe,
                    where the hierarchy is navigable
                 */
    -            if (clazz.isValue())
    +            if (clazz.isPrimitiveClass())
                     clazz = clazz.referenceProjection();
    -            if (this.owner.isValue())
    +            if (this.owner.isPrimitiveClass())
                     return this.projection.isInheritedIn(clazz, types);
     
                 switch ((int)(flags_field & Flags.AccessFlags)) {
    @@ -2332,14 +2331,14 @@ public boolean isLambdaMethod() {
     
             @Override
             public MethodSymbol referenceProjection() {
    -            return this.owner.isValue() ?
    +            return this.owner.isPrimitiveClass() ?
                         this.owner.referenceProjection() != null ? projection : null
                         : null;
             }
     
             @Override
             public MethodSymbol valueProjection() {
    -            return  projection != null ? projection.owner.isValue() ? projection : null : null;
    +            return  projection != null ? projection.owner.isPrimitiveClass() ? projection : null : null;
             }
     
             /** override this method to point to the original enclosing method if this method symbol represents a synthetic
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
    index 7cadd3c63ea..0eef03ae1cc 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
    @@ -271,7 +271,7 @@ public VarSymbol getClassField(Type type, Types types) {
                         /* Temporary treatment for inline class: Given an inline class V that implements
                            I1, I2, ... In, V.class is typed to be Class
                         */
    -                    if (type.isValue()) {
    +                    if (type.isPrimitiveClass()) {
                             List bounds = List.of(objectType).appendList(((ClassSymbol) type.tsym).getInterfaces());
                             arg = new WildcardType(bounds.size() > 1 ? types.makeIntersectionType(bounds) : objectType, BoundKind.EXTENDS, boundClass);
                         } else {
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
    index 8697e46d493..829a95a5776 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
    @@ -235,7 +235,7 @@ public Type(TypeSymbol tsym, TypeMetadata metadata) {
             this.metadata = metadata;
         }
     
    -    public boolean isValue() {
    +    public boolean isPrimitiveClass() {
             return false;
         }
     
    @@ -1195,8 +1195,8 @@ public boolean isReference() {
             }
     
             @Override
    -        public boolean isValue() {
    -            return tsym != null && tsym.isValue();
    +        public boolean isPrimitiveClass() {
    +            return tsym != null && tsym.isPrimitiveClass();
             }
     
             @Override
    @@ -1229,7 +1229,7 @@ public Type valueProjection() {
             @Override
             public ClassType referenceProjection() {
     
    -            if (!isValue() || projection != null)
    +            if (!isPrimitiveClass() || projection != null)
                     return projection;
     
                 // make a best case effort to cache the other projection.
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
    index 7c7da119786..5dbb614e6db 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
    @@ -610,8 +610,8 @@ public boolean isConvertible(Type t, Type s, Warner warn) {
                 return true;
             }
     
    -        boolean tValue = t.isValue();
    -        boolean sValue = s.isValue();
    +        boolean tValue = t.isPrimitiveClass();
    +        boolean sValue = s.isPrimitiveClass();
             if (tValue != sValue) {
                 return tValue ?
                         isSubtype(t.referenceProjection(), s) :
    @@ -1011,8 +1011,8 @@ public boolean accepts(Symbol sym) {
            }
         }
     
    -    public boolean isValue(Type t) {
    -        return t != null && t.tsym != null && (t.tsym.flags_field & Flags.VALUE) != 0;
    +    public boolean isPrimitiveClass(Type t) {
    +        return t != null && t.tsym != null && (t.tsym.flags_field & Flags.PRIMITIVE_CLASS) != 0;
         }
     
         // 
    @@ -1041,9 +1041,9 @@ private boolean isSubtypeUncheckedInternal(Type t, Type s, boolean capture, Warn
                         // if T.ref <: S, then T[] <: S[]
                         Type es = elemtype(s);
                         Type et = elemtype(t);
    -                    if (isValue(et)) {
    +                    if (isPrimitiveClass(et)) {
                             et = et.referenceProjection();
    -                        if (isValue(es))
    +                        if (isPrimitiveClass(es))
                                 es = es.referenceProjection();  // V <: V, surely
                         }
                         if (!isSubtypeUncheckedInternal(et, es, false, warn))
    @@ -1145,7 +1145,7 @@ public Boolean visitType(Type t, Type s) {
                          return isSubtypeNoCapture(t.getUpperBound(), s);
                      case BOT:
                          return
    -                         s.hasTag(BOT) || (s.hasTag(CLASS) && !isValue(s)) ||
    +                         s.hasTag(BOT) || (s.hasTag(CLASS) && !isPrimitiveClass(s)) ||
                              s.hasTag(ARRAY) || s.hasTag(TYPEVAR);
                      case WILDCARD: //we shouldn't be here - avoids crash (see 7034495)
                      case NONE:
    @@ -1227,9 +1227,9 @@ public Boolean visitArrayType(ArrayType t, Type s) {
                             // if T.ref <: S, then T[] <: S[]
                             Type es = elemtype(s);
                             Type et = elemtype(t);
    -                        if (isValue(et)) {
    +                        if (isPrimitiveClass(et)) {
                                 et = et.referenceProjection();
    -                            if (isValue(es))
    +                            if (isPrimitiveClass(es))
                                     es = es.referenceProjection();  // V <: V, surely
                             }
                             return isSubtypeNoCapture(et, es);
    @@ -1722,7 +1722,7 @@ private boolean areDisjoint(ClassSymbol ts, ClassSymbol ss) {
                    subtyping, thereby necessitating special handling.
                 */
                 if ((ss.isReferenceProjection() && ss.valueProjection() == ts) ||
    -                (ss.isValue() && ss.referenceProjection() == ts)) {
    +                (ss.isPrimitiveClass() && ss.referenceProjection() == ts)) {
                     return false;
                 }
                 if (isSubtype(erasure(ts.type), erasure(ss.type))) {
    @@ -1780,7 +1780,7 @@ public Boolean visitWildcardType(WildcardType t, Type s) {
     
                 @Override
                 public Boolean visitClassType(ClassType t, Type s) {
    -                if (s.hasTag(ERROR) || (s.hasTag(BOT) && !isValue(t)))
    +                if (s.hasTag(ERROR) || (s.hasTag(BOT) && !isPrimitiveClass(t)))
                         return true;
     
                     if (s.hasTag(TYPEVAR)) {
    @@ -1799,11 +1799,11 @@ public Boolean visitClassType(ClassType t, Type s) {
                     }
     
                     if (s.hasTag(CLASS) || s.hasTag(ARRAY)) {
    -                    if (isValue(t)) {
    +                    if (isPrimitiveClass(t)) {
                             // (s) Value ? == (s) Value.ref
                             t = t.referenceProjection();
                         }
    -                    if (isValue(s)) {
    +                    if (isPrimitiveClass(s)) {
                             // (Value) t ? == (Value.ref) t
                             s = s.referenceProjection();
                         }
    @@ -2239,15 +2239,15 @@ V.ref is a subtype of I. OIOW, whether asSuper(V.ref, sym) != null. (Likewise fo
                superclass)
             */
             if (checkReferenceProjection)
    -            t = t.isValue() ? t.referenceProjection() : t;
    +            t = t.isPrimitiveClass() ? t.referenceProjection() : t;
     
             if (sym.type == syms.objectType) { //optimization
    -            if (!isValue(t))
    +            if (!isPrimitiveClass(t))
                     return syms.objectType;
             }
             if (sym.type == syms.identityObjectType) {
                 // IdentityObject is super interface of every concrete identity class other than jlO
    -            if (t.isValue() || t.tsym == syms.objectType.tsym)
    +            if (t.isPrimitiveClass() || t.tsym == syms.objectType.tsym)
                     return null;
                 if (t.hasTag(ARRAY))
                     return syms.identityObjectType;
    @@ -2272,7 +2272,7 @@ public Type visitClassType(ClassType t, Symbol sym) {
                         return t;
     
                     // No man may be an island, but the bell tolls for a value.
    -                if (isValue(t))
    +                if (isPrimitiveClass(t))
                         return null;
     
                     Symbol c = t.tsym;
    @@ -2394,10 +2394,10 @@ public Type memberType(Type t, Symbol sym) {
                where the hierarchy is navigable. V and V.ref have identical membership
                with no bridging needs.
             */
    -        if (t.isValue())
    +        if (t.isPrimitiveClass())
                 t = t.referenceProjection();
     
    -        if (sym.owner.isValue())
    +        if (sym.owner.isPrimitiveClass())
                 sym = sym.referenceProjection();
     
             return memberType.visit(t, sym);
    @@ -2611,8 +2611,8 @@ public IntersectionClassType makeIntersectionType(List bounds, boolean all
                 bounds = bounds.prepend(syms.objectType);
             }
             long flags = ABSTRACT | PUBLIC | SYNTHETIC | COMPOUND | ACYCLIC;
    -        if (isValue(bounds.head))
    -            flags |= VALUE;
    +        if (isPrimitiveClass(bounds.head))
    +            flags |= PRIMITIVE_CLASS;
             ClassSymbol bc =
                 new ClassSymbol(flags,
                                 Type.moreInfo
    @@ -5249,7 +5249,7 @@ public void assembleSig(Type type) {
                         if (type.isCompound()) {
                             reportIllegalSignature(type);
                         }
    -                    if (types.isValue(type))
    +                    if (types.isPrimitiveClass(type))
                             append('Q');
                         else
                             append('L');
    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 753f5c42b37..e57979a379b 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
    @@ -167,7 +167,7 @@ protected Attr(Context context) {
             allowLambda = Feature.LAMBDA.allowedInSource(source);
             allowDefaultMethods = Feature.DEFAULT_METHODS.allowedInSource(source);
             allowStaticInterfaceMethods = Feature.STATIC_INTERFACE_METHODS.allowedInSource(source);
    -        allowInlineTypes = Feature.INLINE_TYPES.allowedInSource(source);
    +        allowPrimitiveClasses = Feature.PRIMITIVE_CLASSES.allowedInSource(source);
             allowReifiableTypesInInstanceof =
                     Feature.REIFIABLE_TYPES_INSTANCEOF.allowedInSource(source) &&
                     (!preview.isPreview(Feature.REIFIABLE_TYPES_INSTANCEOF) || preview.isEnabled());
    @@ -201,9 +201,9 @@ protected Attr(Context context) {
          */
         boolean allowDefaultMethods;
     
    -    /** Switch: allow inline types?
    +    /** Switch: allow primitive classes ?
          */
    -    boolean allowInlineTypes;
    +    boolean allowPrimitiveClasses;
     
         /** Switch: static interface methods enabled?
          */
    @@ -329,7 +329,7 @@ void checkAssignable(DiagnosticPosition pos, VarSymbol v, JCTree base, Env positions, List condTypes) {
                 Iterator posIt = positions.iterator();
     
                 condTypes = condTypes.stream()
    -                                 .map(t -> chk.checkNonVoid(posIt.next(), t.isValue() ? t.referenceProjection() : t))
    +                                 .map(t -> chk.checkNonVoid(posIt.next(), t.isPrimitiveClass() ? t.referenceProjection() : t))
                                      .collect(List.collector());
     
                 // both are known to be reference types (or projections).  The result is
    @@ -2549,11 +2549,11 @@ public void visitApply(JCMethodInvocation tree) {
                 if (symbol != null) {
                     /* Is this an ill conceived attempt to invoke jlO methods not available on value types ??
                      */
    -                boolean superCallOnValueReceiver = types.isValue(env.enclClass.sym.type)
    +                boolean superCallOnValueReceiver = types.isPrimitiveClass(env.enclClass.sym.type)
                             && (tree.meth.hasTag(SELECT))
                             && ((JCFieldAccess)tree.meth).selected.hasTag(IDENT)
                             && TreeInfo.name(((JCFieldAccess)tree.meth).selected) == names._super;
    -                if (types.isValue(qualifier) || superCallOnValueReceiver) {
    +                if (types.isPrimitiveClass(qualifier) || superCallOnValueReceiver) {
                         int argSize = argtypes.size();
                         Name name = symbol.name;
                         switch (name.toString()) {
    @@ -2561,7 +2561,7 @@ public void visitApply(JCMethodInvocation tree) {
                                 if (argSize == 0
                                         || (types.isConvertible(argtypes.head, syms.longType) &&
                                         (argSize == 1 || (argSize == 2 && types.isConvertible(argtypes.tail.head, syms.intType))))) {
    -                                log.error(tree.pos(), Errors.ValueDoesNotSupport(name));
    +                                log.error(tree.pos(), Errors.PrimitiveClassDoesNotSupport(name));
                                 }
                                 break;
                             case "notify":
    @@ -2569,13 +2569,13 @@ public void visitApply(JCMethodInvocation tree) {
                             case "clone":
                             case "finalize":
                                 if (argSize == 0)
    -                                log.error(tree.pos(), Errors.ValueDoesNotSupport(name));
    +                                log.error(tree.pos(), Errors.PrimitiveClassDoesNotSupport(name));
                                 break;
                             case "hashCode":
                             case "equals":
                             case "toString":
                                 if (superCallOnValueReceiver)
    -                                log.error(tree.pos(), Errors.ValueDoesNotSupport(names.fromString("invocation of super." + name)));
    +                                log.error(tree.pos(), Errors.PrimitiveClassDoesNotSupport(names.fromString("invocation of super." + name)));
                                 break;
                         }
                     }
    @@ -2598,7 +2598,7 @@ Type adjustMethodReturnType(Symbol msym, Type qualifierType, Name methodName, Li
                     // Temporary treatment for inline class: Given an inline class V that implements
                     // I1, I2, ... In, v.getClass() is typed to be Class
                     Type wcb;
    -                if (qualifierType.isValue()) {
    +                if (qualifierType.isPrimitiveClass()) {
                         List bounds = List.of(syms.objectType).appendList(((ClassSymbol) qualifierType.tsym).getInterfaces());
                         wcb = bounds.size() > 1 ? types.makeIntersectionType(bounds) : syms.objectType;
                     } else {
    @@ -2781,7 +2781,7 @@ public void visitNewClass(final JCNewClass tree) {
                 // Check that it is an instantiation of a class and not a projection type
                 if (clazz.hasTag(SELECT)) {
                     JCFieldAccess fieldAccess = (JCFieldAccess) clazz;
    -                if (fieldAccess.selected.type.isValue() &&
    +                if (fieldAccess.selected.type.isPrimitiveClass() &&
                             (fieldAccess.name == names.ref || fieldAccess.name == names.val)) {
                         log.error(tree.pos(), Errors.ProjectionCantBeInstantiated);
                     }
    @@ -3031,7 +3031,7 @@ public JCExpression makeNullCheck(JCExpression arg) {
             if (arg.getTag() == NEWCLASS)
                 return arg;
             // Likewise arg can't be null if it is a value.
    -        if (types.isValue(arg.type))
    +        if (types.isPrimitiveClass(arg.type))
                 return arg;
             // optimization: X.this is never null; skip null check
             Name name = TreeInfo.name(arg);
    @@ -4256,9 +4256,9 @@ public void visitSelect(JCFieldAccess tree) {
             if (tree.name == names._this || tree.name == names._super ||
                     tree.name == names._class || tree.name == names._default)
             {
    -            if (tree.name == names._default && !allowInlineTypes) {
    +            if (tree.name == names._default && !allowPrimitiveClasses) {
                     log.error(DiagnosticFlag.SOURCE_LEVEL, tree.pos(),
    -                        Feature.INLINE_TYPES.error(sourceName));
    +                        Feature.PRIMITIVE_CLASSES.error(sourceName));
                 }
                 skind = KindSelector.TYP;
             } else {
    @@ -4435,9 +4435,9 @@ private Symbol selectSym(JCFieldAccess tree,
                         return syms.getClassField(site, types);
                     } else if (name == names._default) {
                         return new VarSymbol(STATIC, names._default, site, site.tsym);
    -                } else if (name == names.ref && site.isValue() && resultInfo.pkind.contains(KindSelector.TYP)) {
    +                } else if (name == names.ref && site.isPrimitiveClass() && resultInfo.pkind.contains(KindSelector.TYP)) {
                         return site.tsym.referenceProjection();
    -                } else if (name == names.val && site.isValue() && resultInfo.pkind.contains(KindSelector.TYP)) {
    +                } else if (name == names.val && site.isPrimitiveClass() && resultInfo.pkind.contains(KindSelector.TYP)) {
                         return site.tsym;
                     } else {
                         // We are seeing a plain identifier as selector.
    @@ -5091,7 +5091,7 @@ else if (bound.type.hasTag(CLASS)) {
                     implementing = bounds;
                 }
                 JCClassDecl cd = make.at(tree).ClassDef(
    -                make.Modifiers(PUBLIC | ABSTRACT | (extending != null && TreeInfo.symbol(extending).isValue() ? VALUE : 0)),
    +                make.Modifiers(PUBLIC | ABSTRACT | (extending != null && TreeInfo.symbol(extending).isPrimitiveClass() ? PRIMITIVE_CLASS : 0)),
                     names.empty, List.nil(),
                     extending, implementing, List.nil());
     
    @@ -5221,7 +5221,7 @@ public void attribClass(DiagnosticPosition pos, ClassSymbol c) {
             try {
                 annotate.flush();
                 attribClass(c);
    -            if (types.isValue(c.type)) {
    +            if (types.isPrimitiveClass(c.type)) {
                     final Env env = typeEnvs.get(c);
                     if (!allowValueMemberCycles) {
                         if (env != null && env.tree != null && env.tree.hasTag(CLASSDEF))
    @@ -5393,11 +5393,11 @@ void attribClass(ClassSymbol c) throws CompletionFailure {
     
                     attribClassBody(env, c);
     
    -                if ((c.flags() & (VALUE | ABSTRACT)) == VALUE) { // for non-intersection, concrete values.
    +                if ((c.flags() & (PRIMITIVE_CLASS | ABSTRACT)) == PRIMITIVE_CLASS) { // for non-intersection, concrete values.
                         Assert.check(env.tree.hasTag(CLASSDEF));
                         JCClassDecl classDecl = (JCClassDecl) env.tree;
                         if (classDecl.extending != null) {
    -                        chk.checkConstraintsOfInlineSuper(env.tree.pos(), c);
    +                        chk.checkSuperConstraintsOfPrimitiveClass(env.tree.pos(), c);
                         }
                     }
     
    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 321085787e4..24d543a9199 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
    @@ -737,14 +737,14 @@ private Object asTypeParam(Type t) {
                                         : t;
             }
     
    -    void checkConstraintsOfInlineSuper(DiagnosticPosition pos, ClassSymbol c) {
    +    void checkSuperConstraintsOfPrimitiveClass(DiagnosticPosition pos, ClassSymbol c) {
             for(Type st = types.supertype(c.type); st != Type.noType; st = types.supertype(st)) {
                 if (st == null || st.tsym == null || st.tsym.kind == ERR)
                     return;
                 if  (st.tsym == syms.objectType.tsym)
                     return;
                 if (!st.tsym.isAbstract()) {
    -                log.error(pos, Errors.ConcreteSupertypeForInlineClass(c, st));
    +                log.error(pos, Errors.ConcreteSupertypeForPrimitiveClass(c, st));
                 }
                 if ((st.tsym.flags() & HASINITBLOCK) != 0) {
                     log.error(pos, Errors.SuperClassDeclaresInitBlock(c, st));
    @@ -795,7 +795,7 @@ Type checkConstructorRefType(JCExpression expr, Type t) {
                     // Projection types may not be mentioned in constructor references
                     if (expr.hasTag(SELECT)) {
                         JCFieldAccess fieldAccess = (JCFieldAccess) expr;
    -                    if (fieldAccess.selected.type.isValue() &&
    +                    if (fieldAccess.selected.type.isPrimitiveClass() &&
                                 (fieldAccess.name == names.ref || fieldAccess.name == names.val)) {
                             log.error(expr, Errors.ProjectionCantBeInstantiated);
                             t = types.createErrorType(t);
    @@ -839,7 +839,7 @@ Type checkClassType(DiagnosticPosition pos, Type t, boolean noBounds) {
          *  @param valueOK       If false, a value class does not qualify
          */
         Type checkRefType(DiagnosticPosition pos, Type t, boolean valueOK) {
    -        if (t.isReference() && (valueOK || !types.isValue(t)))
    +        if (t.isReference() && (valueOK || !types.isPrimitiveClass(t)))
                 return t;
             else
                 return typeTagError(pos,
    @@ -917,8 +917,8 @@ public Void visitType(Type t, DiagnosticPosition pos) {
             @Override
             public Void visitClassType(ClassType t, DiagnosticPosition pos) {
                 for (Type targ : t.allparams()) {
    -                if (types.isValue(targ)) {
    -                    log.error(pos, Errors.GenericParameterizationWithValueType(t));
    +                if (types.isPrimitiveClass(targ)) {
    +                    log.error(pos, Errors.GenericParameterizationWithPrimitiveClass(t));
                     }
                     visit(targ, pos);
                 }
    @@ -1333,7 +1333,7 @@ else if ((sym.owner.flags_field & INTERFACE) != 0)
                     mask = implicit = InterfaceVarFlags;
                 else {
                     mask = VarFlags;
    -                if (types.isValue(sym.owner.type) && (flags & STATIC) == 0) {
    +                if (types.isPrimitiveClass(sym.owner.type) && (flags & STATIC) == 0) {
                         implicit |= FINAL;
                     }
                 }
    @@ -1365,7 +1365,7 @@ else if ((sym.owner.flags_field & INTERFACE) != 0)
                     mask = RecordMethodFlags;
                 } else {
                     // instance methods of value types do not have a monitor associated with their `this'
    -                mask = ((sym.owner.flags_field & VALUE) != 0 && (flags & Flags.STATIC) == 0) ?
    +                mask = ((sym.owner.flags_field & PRIMITIVE_CLASS) != 0 && (flags & Flags.STATIC) == 0) ?
                             MethodFlags & ~SYNCHRONIZED : MethodFlags;
                 }
                 // Imply STRICTFP if owner has STRICTFP set.
    @@ -1401,7 +1401,7 @@ else if ((sym.owner.flags_field & INTERFACE) != 0)
     
                 if ((flags & ENUM) != 0) {
                     // enums can't be declared abstract, final, sealed or non-sealed or value type
    -                mask &= ~(ABSTRACT | FINAL | SEALED | NON_SEALED | VALUE);
    +                mask &= ~(ABSTRACT | FINAL | SEALED | NON_SEALED | PRIMITIVE_CLASS);
                     implicit |= implicitEnumFinalFlag(tree);
                 }
                 if ((flags & RECORD) != 0) {
    @@ -1439,7 +1439,7 @@ else if ((sym.kind == TYP ||
                      &&
                      checkDisjoint(pos, flags,
                                    ABSTRACT | INTERFACE,
    -                               FINAL | NATIVE | SYNCHRONIZED | VALUE)
    +                               FINAL | NATIVE | SYNCHRONIZED | PRIMITIVE_CLASS)
                      &&
                      checkDisjoint(pos, flags,
                                    PUBLIC,
    @@ -1959,10 +1959,10 @@ void checkOverride(JCTree tree,
                 return;
             }
     
    -        if (origin.isValue() && other.owner == syms.objectType.tsym && m.type.getParameterTypes().size() == 0) {
    +        if (origin.isPrimitiveClass() && other.owner == syms.objectType.tsym && m.type.getParameterTypes().size() == 0) {
                 if (m.name == names.clone || m.name == names.finalize) {
                     log.error(TreeInfo.diagnosticPositionFor(m, tree),
    -                        Errors.InlineClassMayNotOverride(m.name));
    +                        Errors.PrimitiveClassMayNotOverride(m.name));
                     m.flags_field |= BAD_OVERRIDE;
                     return;
                 }
    @@ -2281,7 +2281,7 @@ void checkOverride(Env env, JCMethodDecl tree, MethodSymbol m) {
             // be treated "as if as they were annotated" with @Override.
             boolean mustOverride = explicitOverride ||
                     (env.info.isAnonymousDiamond && !m.isConstructor() && !m.isPrivate() &&
    -                        (!m.owner.isValue() || (tree.body.flags & SYNTHETIC) == 0));
    +                        (!m.owner.isPrimitiveClass() || (tree.body.flags & SYNTHETIC) == 0));
             if (mustOverride && !isOverrider(m)) {
                 DiagnosticPosition pos = tree.pos();
                 for (JCAnnotation a : tree.getModifiers().annotations) {
    @@ -2429,7 +2429,7 @@ void checkNonCyclicMembership(JCClassDecl tree) {
         // where
         private void checkNonCyclicMembership(ClassSymbol c, DiagnosticPosition pos) {
             if ((c.flags_field & LOCKED) != 0) {
    -            log.error(pos, Errors.CyclicValueTypeMembership(c));
    +            log.error(pos, Errors.CyclicPrimitiveClassMembership(c));
                 return;
             }
             try {
    @@ -2443,7 +2443,7 @@ private void checkNonCyclicMembership(ClassSymbol c, DiagnosticPosition pos) {
         }
             // where
             private boolean cyclePossible(VarSymbol symbol) {
    -            return (symbol.flags() & STATIC) == 0 && types.isValue(symbol.type);
    +            return (symbol.flags() & STATIC) == 0 && types.isPrimitiveClass(symbol.type);
             }
     
         void checkNonCyclicDecl(JCClassDecl tree) {
    @@ -2695,8 +2695,8 @@ void checkCompatibleSupertypes(DiagnosticPosition pos, Type c) {
             }
             checkCompatibleConcretes(pos, c);
     
    -        if (c.isValue() && types.asSuper(c, syms.identityObjectType.tsym, true) != null) {
    -            log.error(pos, Errors.InlineTypeMustNotImplementIdentityObject(c));
    +        if (c.isPrimitiveClass() && types.asSuper(c, syms.identityObjectType.tsym, true) != null) {
    +            log.error(pos, Errors.PrimitiveClassMustNotImplementIdentityObject(c));
             }
         }
     
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java
    index 9d5f8564b88..772b2169f5d 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java
    @@ -496,7 +496,7 @@ public void visitClassDef(JCClassDecl tree) {
             // Enter type parameters.
             ct.typarams_field = classEnter(tree.typarams, localEnv);
             ct.allparams_field = null;
    -        if (ct.isValue()) {
    +        if (ct.isPrimitiveClass()) {
                 if (ct.projection != null) {
                     ct.projection.typarams_field = ct.typarams_field;
                     ct.projection.allparams_field = ct.allparams_field;
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
    index 0a88344335f..b2fd74e333c 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
    @@ -2124,7 +2124,7 @@ public void visitMethodDef(JCMethodDecl tree) {
                             firstadr = nextadr;
                             this.thisExposability = ALLOWED;
                         } else {
    -                        if (types.isValue(tree.sym.owner.type))
    +                        if (types.isPrimitiveClass(tree.sym.owner.type))
                                 this.thisExposability = BANNED;
                             else
                                 this.thisExposability = ALLOWED;
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
    index 94dda379d14..557fc0e58aa 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
    @@ -2340,7 +2340,7 @@ final boolean needsConversionToLambda() {
                             receiverIsReferenceProjection() ||
                             (tree.getMode() == ReferenceMode.NEW &&
                               tree.kind != ReferenceKind.ARRAY_CTOR &&
    -                          (tree.sym.owner.isDirectlyOrIndirectlyLocal() || tree.sym.owner.isInner() || tree.sym.owner.isValue()));
    +                          (tree.sym.owner.isDirectlyOrIndirectlyLocal() || tree.sym.owner.isInner() || tree.sym.owner.isPrimitiveClass()));
                 }
     
                 Type generatedRefSig() {
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
    index 64aff6eac96..6420ba4a151 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
    @@ -93,11 +93,8 @@ public static Lower instance(Context context) {
         private DiagnosticPosition make_pos;
         private final ConstFold cfolder;
         private final Target target;
    -    private final Source source;
         private final TypeEnvs typeEnvs;
         private final Name dollarAssertionsDisabled;
    -    private final Name classDollar;
    -    private final Name dollarCloseResource;
         private final Types types;
         private final boolean debugLower;
         private final boolean disableProtectedAccessors; // experimental
    @@ -115,14 +112,9 @@ protected Lower(Context context) {
             make = TreeMaker.instance(context);
             cfolder = ConstFold.instance(context);
             target = Target.instance(context);
    -        source = Source.instance(context);
             typeEnvs = TypeEnvs.instance(context);
             dollarAssertionsDisabled = names.
                 fromString(target.syntheticNameChar() + "assertionsDisabled");
    -        classDollar = names.
    -            fromString("class" + target.syntheticNameChar());
    -        dollarCloseResource = names.
    -            fromString(target.syntheticNameChar() + "closeResource");
     
             types = Types.instance(context);
             Options options = Options.instance(context);
    @@ -2100,7 +2092,7 @@ public  T translate(T tree) {
          */
         public  T translate(T tree, Type type) {
             return (tree == null) ? null :
    -                applyInlineConversionsAsNeeded(boxIfNeeded(translate(tree), type), type);
    +                applyPrimitiveConversionsAsNeeded(boxIfNeeded(translate(tree), type), type);
         }
     
         /** Visitor method: Translate tree.
    @@ -3097,11 +3089,11 @@ List boxArgs(List parameters, List _args, Type
             return result.toList();
         }
     
    -    /** Apply inline widening/narrowing conversions as needed */
    +    /** Apply primitive value/reference conversions as needed */
         @SuppressWarnings("unchecked")
    -     T applyInlineConversionsAsNeeded(T tree, Type type) {
    -        boolean haveValue = tree.type.isValue();
    -        if (haveValue == type.isValue())
    +     T applyPrimitiveConversionsAsNeeded(T tree, Type type) {
    +        boolean haveValue = tree.type.isPrimitiveClass();
    +        if (haveValue == type.isPrimitiveClass())
                 return tree;
             if (haveValue) {
                 // widening coversion is a NOP for the VM due to subtyping relationship at class file
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java
    index 2e19711daee..0dfb2e401ce 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java
    @@ -218,7 +218,7 @@ public void visitMethodDef(JCMethodDecl tree) {
     
             localEnv.info.scope.leave();
             if (chk.checkUnique(tree.pos(), m, enclScope)) {
    -            ClassSymbol refProjection = m.owner.isValue() ? (ClassSymbol) m.owner.referenceProjection() : null;
    +            ClassSymbol refProjection = m.owner.isPrimitiveClass() ? (ClassSymbol) m.owner.referenceProjection() : null;
                 enclScope.enter(m);
                 if (refProjection != null) {
                     MethodSymbol clone = m.clone(refProjection);
    @@ -300,7 +300,7 @@ public void visitVarDef(JCVariableDecl tree) {
             */
             if (tree.init != null) {
                 v.flags_field |= HASINIT;
    -            if ((v.flags_field & FINAL) != 0 && ((v.flags_field & STATIC) != 0 || !types.isValue(v.owner.type)) &&
    +            if ((v.flags_field & FINAL) != 0 && ((v.flags_field & STATIC) != 0 || !types.isPrimitiveClass(v.owner.type)) &&
                     needsLazyConstValue(tree.init)) {
                     Env initEnv = getInitEnv(tree, env);
                     initEnv.info.enclVar = v;
    @@ -309,7 +309,7 @@ public void visitVarDef(JCVariableDecl tree) {
             }
             if (chk.checkUnique(tree.pos(), v, enclScope)) {
                 chk.checkTransparentVar(tree.pos(), v, enclScope);
    -            ClassSymbol refProjection =  v.owner.isValue() ? (ClassSymbol) v.owner.referenceProjection() : null;
    +            ClassSymbol refProjection =  v.owner.isPrimitiveClass() ? (ClassSymbol) v.owner.referenceProjection() : null;
                 enclScope.enter(v);
                 if (refProjection != null) {
                     VarSymbol clone = v.clone(refProjection);
    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 08e785e5440..a7afb790779 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
    @@ -418,11 +418,11 @@ public boolean isAccessible(Env env, Type site, Symbol sym, boolean
                 /* If any inline types are involved, ask the same question in the reference universe,
                    where the hierarchy is navigable
                 */
    -            if (site.isValue())
    +            if (site.isPrimitiveClass())
                     site = site.referenceProjection();
    -            if (sym.owner.isValue())
    +            if (sym.owner.isPrimitiveClass())
                     sym = sym.referenceProjection();
    -            if (env.enclClass.sym.isValue())
    +            if (env.enclClass.sym.isPrimitiveClass())
                     env.enclClass.sym = env.enclClass.sym.referenceProjection();
             } else if (sym.kind == TYP) {
                 // A type is accessible in a reference projection if it was
    @@ -487,9 +487,9 @@ private boolean notOverriddenIn(Type site, Symbol sym) {
             /* If any inline types are involved, ask the same question in the reference universe,
                where the hierarchy is navigable
             */
    -        if (site.isValue())
    +        if (site.isPrimitiveClass())
                 site = site.referenceProjection();
    -        if (sym.owner.isValue())
    +        if (sym.owner.isPrimitiveClass())
                 sym = sym.referenceProjection();
     
             Symbol s2 = ((MethodSymbol)sym).implementation(site.tsym, types, true);
    @@ -3063,7 +3063,7 @@ public Symbol baseSymbol() {
                                 return sym;
                             }
                         };
    -                    ClassSymbol refProjection = newConstr.owner.isValue() ?
    +                    ClassSymbol refProjection = newConstr.owner.isPrimitiveClass() ?
                                                          (ClassSymbol) newConstr.owner.referenceProjection() : null;
                         if (refProjection != null) {
                             MethodSymbol clone = newConstr.clone(refProjection);
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java
    index 8e6d0e6f150..04141e35552 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -26,13 +26,14 @@
     package com.sun.tools.javac.comp;
     
     import com.sun.tools.javac.code.Flags;
    +import com.sun.tools.javac.code.Kinds;
    +import com.sun.tools.javac.code.Kinds.Kind;
     import com.sun.tools.javac.code.Symbol;
     import com.sun.tools.javac.code.Symbol.BindingSymbol;
     import com.sun.tools.javac.code.Symbol.VarSymbol;
     import com.sun.tools.javac.code.Symtab;
     import com.sun.tools.javac.code.Type;
     import com.sun.tools.javac.code.Types;
    -import com.sun.tools.javac.tree.JCTree;
     import com.sun.tools.javac.tree.JCTree.JCAssign;
     import com.sun.tools.javac.tree.JCTree.JCBinary;
     import com.sun.tools.javac.tree.JCTree.JCConditional;
    @@ -49,7 +50,6 @@
     import com.sun.tools.javac.tree.JCTree.Tag;
     import com.sun.tools.javac.tree.TreeMaker;
     import com.sun.tools.javac.tree.TreeTranslator;
    -import com.sun.tools.javac.util.Assert;
     import com.sun.tools.javac.util.Context;
     import com.sun.tools.javac.util.ListBuffer;
     import com.sun.tools.javac.util.Log;
    @@ -68,6 +68,7 @@
     import com.sun.tools.javac.tree.JCTree.JCLambda;
     import com.sun.tools.javac.tree.JCTree.JCStatement;
     import com.sun.tools.javac.tree.JCTree.LetExpr;
    +import com.sun.tools.javac.tree.TreeInfo;
     import com.sun.tools.javac.util.List;
     import java.util.HashMap;
     
    @@ -152,15 +153,23 @@ public void visitTypeTest(JCInstanceOf tree) {
                 //E instanceof T N
                 //=>
                 //(let T' N$temp = E; N$temp instanceof T && (N = (T) N$temp == (T) N$temp))
    +            Symbol exprSym = TreeInfo.symbol(tree.expr);
                 JCBindingPattern patt = (JCBindingPattern)tree.pattern;
                 VarSymbol pattSym = patt.var.sym;
                 Type tempType = tree.expr.type.hasTag(BOT) ?
                         syms.objectType
                         : tree.expr.type;
    -            VarSymbol temp = new VarSymbol(pattSym.flags() | Flags.SYNTHETIC,
    -                    names.fromString(pattSym.name.toString() + target.syntheticNameChar() + "temp"),
    -                    tempType,
    -                    patt.var.sym.owner);
    +            VarSymbol temp;
    +            if (exprSym != null &&
    +                exprSym.kind == Kind.VAR &&
    +                exprSym.owner.kind.matches(Kinds.KindSelector.VAL_MTH)) {
    +                temp = (VarSymbol) exprSym;
    +            } else {
    +                temp = new VarSymbol(pattSym.flags() | Flags.SYNTHETIC,
    +                        names.fromString(pattSym.name.toString() + target.syntheticNameChar() + "temp"),
    +                        tempType,
    +                        patt.var.sym.owner);
    +            }
                 JCExpression translatedExpr = translate(tree.expr);
                 Type castTargetType = types.boxedTypeOrType(pattSym.erasure(types));
     
    @@ -176,8 +185,10 @@ public void visitTypeTest(JCInstanceOf tree) {
                     nestedLE.setType(syms.booleanType);
                     result = makeBinary(Tag.AND, (JCExpression)result, nestedLE);
                 }
    -            result = make.at(tree.pos).LetExpr(make.VarDef(temp, translatedExpr), (JCExpression)result).setType(syms.booleanType);
    -            ((LetExpr) result).needsCond = true;
    +            if (temp != exprSym) {
    +                result = make.at(tree.pos).LetExpr(make.VarDef(temp, translatedExpr), (JCExpression)result).setType(syms.booleanType);
    +                ((LetExpr) result).needsCond = true;
    +            }
             } else {
                 super.visitTypeTest(tree);
             }
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java
    index 504c281c70b..69053f2691c 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java
    @@ -288,7 +288,7 @@ void addBridge(DiagnosticPosition pos,
             bridges.append(md);
     
             // Add bridge to scope of enclosing class and keep track of the bridge span.
    -        ClassSymbol refProjection = origin.isValue() ? origin.referenceProjection() : null;
    +        ClassSymbol refProjection = origin.isPrimitiveClass() ? origin.referenceProjection() : null;
             origin.members().enter(bridge);
             if (refProjection != null) {
                 MethodSymbol clone = bridge.clone(refProjection);
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
    index 2eb80a226ca..7ce91f949cf 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
    @@ -681,7 +681,7 @@ protected void attribSuperTypes(Env env, Env baseEnv)
                 // Determine supertype.
                 Type supertype;
                 JCExpression extending;
    -            final boolean isValueType = (tree.mods.flags & Flags.VALUE) != 0;
    +            final boolean isValueType = (tree.mods.flags & Flags.PRIMITIVE_CLASS) != 0;
     
                 if (tree.extending != null) {
                     extending = clearTypeParams(tree.extending);
    @@ -733,7 +733,7 @@ protected void attribSuperTypes(Env env, Env baseEnv)
                     ct.all_interfaces_field = (all_interfaces == null)
                             ? ct.interfaces_field : all_interfaces.toList();
                 }
    -            if (ct.isValue()) {
    +            if (ct.isPrimitiveClass()) {
                     ClassSymbol cSym = (ClassSymbol) ct.tsym;
                     if (cSym.projection != null) {
                         ClassType projectedType = (ClassType) cSym.projection.type;
    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 d7692f05fbe..7754dfc799b 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
    @@ -105,9 +105,9 @@ public class ClassReader {
          */
         boolean allowModules;
     
    -    /** Switch: allow inline types.
    +    /** Switch: allow primitive classes.
          */
    -    boolean allowInlineTypes;
    +    boolean allowPrimitiveClasses;
     
         /** Switch: allow sealed
          */
    @@ -276,7 +276,7 @@ protected ClassReader(Context context) {
             Source source = Source.instance(context);
             preview = Preview.instance(context);
             allowModules     = Feature.MODULES.allowedInSource(source);
    -        allowInlineTypes = Feature.INLINE_TYPES.allowedInSource(source);
    +        allowPrimitiveClasses = Feature.PRIMITIVE_CLASSES.allowedInSource(source);
             allowRecords = Feature.RECORDS.allowedInSource(source);
             allowSealedTypes = (!preview.isPreview(Feature.SEALED_CLASSES) || preview.isEnabled()) &&
                     Feature.SEALED_CLASSES.allowedInSource(source);
    @@ -297,7 +297,7 @@ protected ClassReader(Context context) {
         private void enterMember(ClassSymbol c, Symbol sym) {
             // Synthetic members are not entered -- reason lost to history (optimization?).
             // Lambda methods must be entered because they may have inner classes (which reference them)
    -        ClassSymbol refProjection =  c.isValue() ? c.referenceProjection() : null;
    +        ClassSymbol refProjection =  c.isPrimitiveClass() ? c.referenceProjection() : null;
             if ((sym.flags_field & (SYNTHETIC|BRIDGE)) != SYNTHETIC || sym.name.startsWith(names.lambda)) {
                 c.members_field.enter(sym);
                 if (refProjection != null) {
    @@ -813,7 +813,7 @@ private void initAttributeReaders() {
     
                 new AttributeReader(names.Code, V45_3, MEMBER_ATTRIBUTE) {
                     protected void read(Symbol sym, int attrLen) {
    -                    if (allowInlineTypes) {
    +                    if (allowPrimitiveClasses) {
                             if (sym.isConstructor()  && ((MethodSymbol) sym).type.getParameterTypes().size() == 0) {
                                 int code_length = buf.getInt(bp + 4);
                                 if ((code_length == 1 && buf.getByte( bp + 8) == (byte) ByteCodes.return_) ||
    @@ -1004,7 +1004,7 @@ protected void read(Symbol sym, int attrLen) {
                             //- System.err.println(" # " + sym.type);
                             if (sym.kind == MTH && sym.type.getThrownTypes().isEmpty())
                                 sym.type.asMethodType().thrown = thrown;
    -                        if (sym.kind == MTH  && sym.name == names.init && sym.owner.isValue()) {
    +                        if (sym.kind == MTH  && sym.name == names.init && sym.owner.isPrimitiveClass()) {
                                 sym.type = new MethodType(sym.type.getParameterTypes(),
                                         syms.voidType,
                                         sym.type.getThrownTypes(),
    @@ -1280,7 +1280,7 @@ protected void read(Symbol sym, int attrLen) {
                 new AttributeReader(names.RestrictedField, V60, MEMBER_ATTRIBUTE) {
                     @Override
                     protected boolean accepts(AttributeKind kind) {
    -                    return super.accepts(kind) && allowInlineTypes;
    +                    return super.accepts(kind) && allowPrimitiveClasses;
                     }
                     protected void read(Symbol sym, int attrLen) {
                         if (sym.kind == VAR && sym.owner.kind == TYP) {
    @@ -1296,7 +1296,7 @@ protected void read(Symbol sym, int attrLen) {
                 new AttributeReader(names.RestrictedMethod, V60, MEMBER_ATTRIBUTE) {
                     @Override
                     protected boolean accepts(AttributeKind kind) {
    -                    return super.accepts(kind) && allowInlineTypes;
    +                    return super.accepts(kind) && allowPrimitiveClasses;
                     }
                     protected void read(Symbol sym, int attrLen) {
                         if (!types.flattenWithTypeRestrictions) {
    @@ -2554,7 +2554,7 @@ protected void enterTypevars(Symbol sym, Type t) {
         }
     
         protected ClassSymbol enterClass(Name name) {
    -        if (allowInlineTypes && name.toString().endsWith("$ref")) {
    +        if (allowPrimitiveClasses && name.toString().endsWith("$ref")) {
                 ClassSymbol v = syms.enterClass(currentModule, name.subName(0, name.length() - 4));
                 return v.referenceProjection();
             }
    @@ -2725,7 +2725,7 @@ private void readClassBuffer(ClassSymbol c) throws IOException {
     
         public void readClassFile(ClassSymbol c) {
             readClassFileInternal(c);
    -        if (c.isValue()) {
    +        if (c.isPrimitiveClass()) {
                 /* http://cr.openjdk.java.net/~briangoetz/valhalla/sov/04-translation.html
                    The relationship of value and reference projections differs between the language model
                    and the VM model. In the language, the value projection is not a subtype of the
    @@ -2845,10 +2845,10 @@ long adjustClassFlags(long flags) {
                 flags &= ~ACC_MODULE;
                 flags |= MODULE;
             }
    -        if ((flags & ACC_INLINE) != 0) {
    -            flags &= ~ACC_INLINE;
    -            if (allowInlineTypes) {
    -                flags |= VALUE;
    +        if ((flags & ACC_PRIMITIVE) != 0) {
    +            flags &= ~ACC_PRIMITIVE;
    +            if (allowPrimitiveClasses) {
    +                flags |= PRIMITIVE_CLASS;
                 }
             }
             return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
    index c28ee310c8b..c8fcea11185 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
    @@ -868,7 +868,7 @@ int writeRecordAttribute(ClassSymbol csym) {
         int writeNestMembersIfNeeded(ClassSymbol csym) {
             Set nestedUnique = new LinkedHashSet<>();
             if (csym.owner.kind == PCK) {
    -            if (csym.isValue()) {
    +            if (csym.isPrimitiveClass()) {
                     // reference projection is the host
                 } else if (csym.isReferenceProjection()) {
                     ClassSymbol valueProjection = csym.valueProjection();
    @@ -894,10 +894,10 @@ int writeNestMembersIfNeeded(ClassSymbol csym) {
          * Write NestHost attribute (if needed)
          */
         int writeNestHostIfNeeded(ClassSymbol csym) {
    -        if (csym.owner.kind != PCK || csym.isValue()) {
    +        if (csym.owner.kind != PCK || csym.isPrimitiveClass()) {
                 int alenIdx = writeAttr(names.NestHost);
                 ClassSymbol outerMost = csym.outermostClass();
    -            if (outerMost.isValue()) {
    +            if (outerMost.isPrimitiveClass()) {
                     outerMost = outerMost.referenceProjection();
                 }
                 databuf.appendChar(poolWriter.putClass(outerMost));
    @@ -912,7 +912,7 @@ private void listNested(Symbol sym, Set seen) {
             ClassSymbol csym = (ClassSymbol)sym;
             if (csym.owner.kind != PCK) {
                 seen.add(csym);
    -            if (csym.isValue()) {
    +            if (csym.isPrimitiveClass()) {
                     seen.add(csym.referenceProjection());
                 }
             }
    @@ -975,7 +975,7 @@ void writeField(VarSymbol v) {
             databuf.appendChar(poolWriter.putName(v.name));
             boolean emitRestrictedField = false;
             int restrictedFieldDescriptor = 0;
    -        if (types.flattenWithTypeRestrictions && v.type.isValue()) {
    +        if (types.flattenWithTypeRestrictions && v.type.isPrimitiveClass()) {
                 emitRestrictedField = true;
                 databuf.appendChar(poolWriter.putDescriptor(v.type.referenceProjection()));
             } else {
    @@ -1001,7 +1001,7 @@ void writeField(VarSymbol v) {
             }
             if (emitRestrictedField) {
                 int alenIdx = writeAttr(names.RestrictedField);
    -            if (types.flattenWithTypeRestrictions && v.type.isValue()) {
    +            if (types.flattenWithTypeRestrictions && v.type.isPrimitiveClass()) {
                     databuf.appendChar(poolWriter.putDescriptor(v));
                 }   else {
                     databuf.appendChar(restrictedFieldDescriptor);
    @@ -1059,13 +1059,13 @@ void writeMethod(MethodSymbol m) {
     
             if (types.flattenWithTypeRestrictions && m.name == m.name.table.names.init && m.owner.hasOuterInstance()) {
                 Type outerThisType = types.erasure(m.owner.type.getEnclosingType());
    -            if (outerThisType.isValue()) {
    +            if (outerThisType.isPrimitiveClass()) {
                     emitRestrictedMethod = true;
                 }
             }
             CheckTypeRestrictedParameters:
             for (Type pt : m.type.getParameterTypes()) {
    -            if (pt.isValue() && types.flattenWithTypeRestrictions) {
    +            if (pt.isPrimitiveClass() && types.flattenWithTypeRestrictions) {
                     emitRestrictedMethod = true;
                     break;
                 }
    @@ -1076,7 +1076,7 @@ void writeMethod(MethodSymbol m) {
                     }
                 }
             }
    -        if (m.type.getReturnType().isValue() && types.flattenWithTypeRestrictions) {
    +        if (m.type.getReturnType().isPrimitiveClass() && types.flattenWithTypeRestrictions) {
                 emitRestrictedMethod = true;
             } else {
                 for (Attribute.Compound anno : m.type.getReturnType().getAnnotationMirrors()) {
    @@ -1093,13 +1093,13 @@ void writeMethod(MethodSymbol m) {
                 if (types.flattenWithTypeRestrictions) {
                     if (m.name == names.init && m.owner.hasOuterInstance()) {
                         Type outerThisType = types.erasure(m.owner.type.getEnclosingType());
    -                    databuf.appendChar(outerThisType.isValue() ? poolWriter.putDescriptor(outerThisType) : 0);
    +                    databuf.appendChar(outerThisType.isPrimitiveClass() ? poolWriter.putDescriptor(outerThisType) : 0);
                     }
                     for (Type pt : m.erasure(types).getParameterTypes()) {
    -                    databuf.appendChar(pt.isValue() ? poolWriter.putDescriptor(pt) : 0);
    +                    databuf.appendChar(pt.isPrimitiveClass() ? poolWriter.putDescriptor(pt) : 0);
                     }
                     Type rt = m.erasure(types).getReturnType();
    -                databuf.appendChar(rt.isValue() ? poolWriter.putDescriptor(rt) : 0);
    +                databuf.appendChar(rt.isPrimitiveClass() ? poolWriter.putDescriptor(rt) : 0);
                 } else {
                     int restrictedTypeDescriptor;
                     for (Type pt : m.type.getParameterTypes()) {
    @@ -1347,7 +1347,7 @@ else switch(t.getTag()) {
                 case ARRAY:
                     if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")");
                     databuf.appendByte(7);
    -                databuf.appendChar(types.isValue(t) ? poolWriter.putClass(new ConstantPoolQType(types.erasure(t), types)) : poolWriter.putClass(types.erasure(t)));
    +                databuf.appendChar(types.isPrimitiveClass(t) ? poolWriter.putClass(new ConstantPoolQType(types.erasure(t), types)) : poolWriter.putClass(types.erasure(t)));
                     break;
                 case TYPEVAR:
                     if (debugstackmap) System.out.print("object(" + types.erasure(t).tsym + ")");
    @@ -1612,7 +1612,7 @@ public JavaFileObject writeClass(ClassSymbol c)
             throws IOException, PoolOverflow, StringOverflow
         {
             JavaFileObject javaFileObject = writeClassInternal(c);
    -        if (c.isValue()) {
    +        if (c.isPrimitiveClass()) {
                 ClassSymbol refProjection = c.referenceProjection();
                 refProjection.flags_field = (refProjection.flags_field & ~FINAL) | ABSTRACT;
                 writeClassInternal(refProjection);
    @@ -1664,8 +1664,8 @@ public void writeClassFile(OutputStream out, ClassSymbol c)
             databuf.reset();
             poolbuf.reset();
     
    -        Type supertype = c.isValue() ? c.type.referenceProjection() : types.supertype(c.type);
    -        List interfaces = c.isValue() ? List.nil() : types.interfaces(c.type);
    +        Type supertype = c.isPrimitiveClass() ? c.type.referenceProjection() : types.supertype(c.type);
    +        List interfaces = c.isPrimitiveClass() ? List.nil() : types.interfaces(c.type);
             List typarams = c.type.getTypeArguments();
     
             int flags;
    @@ -1674,7 +1674,7 @@ public void writeClassFile(OutputStream out, ClassSymbol c)
             } else {
                 flags = adjustFlags(c.flags() & ~DEFAULT);
                 if ((flags & PROTECTED) != 0) flags |= PUBLIC;
    -            flags = flags & (ClassFlags | ACC_INLINE) & ~STRICTFP;
    +            flags = flags & (ClassFlags | ACC_PRIMITIVE) & ~STRICTFP;
                 if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
             }
     
    @@ -1851,8 +1851,8 @@ int adjustFlags(final long flags) {
                 result |= ACC_VARARGS;
             if ((flags & DEFAULT) != 0)
                 result &= ~ABSTRACT;
    -        if ((flags & VALUE) != 0)
    -            result |= ACC_INLINE;
    +        if ((flags & PRIMITIVE_CLASS) != 0)
    +            result |= ACC_PRIMITIVE;
             return result;
         }
     
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java
    index f57982e380c..5c367b8e477 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java
    @@ -1782,7 +1782,7 @@ void forceStackTop(Type t) {
                     int width = width(t);
                     Type old = stack[stacksize-width];
                     Assert.check(types.isSubtype(types.erasure(old), types.erasure(t)) ||
    -                        (old.isValue() != t.isValue() && types.isConvertible(types.erasure(old), types.erasure(t))));
    +                        (old.isPrimitiveClass() != t.isPrimitiveClass() && types.isConvertible(types.erasure(old), types.erasure(t))));
                     stack[stacksize-width] = t;
                     break;
                 default:
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
    index 4a71fbfe4fe..f1348348028 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java
    @@ -2046,7 +2046,7 @@ Item makeNewArray(DiagnosticPosition pos, Type type, int ndims) {
                 }
                 int elemcode = Code.arraycode(elemtype);
                 if (elemcode == 0 || (elemcode == 1 && ndims == 1)) {
    -                code.emitAnewarray(makeRef(pos, elemtype, types.isValue(elemtype)), type);
    +                code.emitAnewarray(makeRef(pos, elemtype, types.isPrimitiveClass(elemtype)), type);
                 } else if (elemcode == 1) {
                     code.emitMultianewarray(ndims, makeRef(pos, type), type);
                 } else {
    @@ -2278,7 +2278,7 @@ public void visitTypeCast(JCTypeCast tree) {
                 (!tree.clazz.type.tsym.isReferenceProjection() || tree.clazz.type.tsym.valueProjection() != tree.expr.type.tsym) &&
                types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
                 checkDimension(tree.pos(), tree.clazz.type);
    -            if (types.isValue(tree.clazz.type)) {
    +            if (types.isPrimitiveClass(tree.clazz.type)) {
                     code.emitop2(checkcast, new ConstantPoolQType(tree.clazz.type, types), PoolWriter::putClass);
                 } else {
                     code.emitop2(checkcast, tree.clazz.type, PoolWriter::putClass);
    @@ -2349,7 +2349,7 @@ public void visitSelect(JCFieldAccess tree) {
                 result = items.makeStackItem(pt);
                 return;
             } else if (tree.name == names._default) {
    -            if (tree.type.asElement().isValue()) {
    +            if (tree.type.asElement().isPrimitiveClass()) {
                     code.emitop2(defaultvalue, checkDimension(tree.pos(), tree.type), PoolWriter::putClass);
                 } else if (tree.type.isReference()) {
                     code.emitop0(aconst_null);
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java
    index 6016415abf2..deaf3c100c5 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java
    @@ -148,7 +148,7 @@ private LocalItem makeLocalItem(Type type, int reg) {
          *  @param member   The represented symbol.
          */
         Item makeStaticItem(Symbol member) {
    -        if (this.types.flattenWithTypeRestrictions && member.kind == Kind.VAR && member.type.isValue()) {
    +        if (this.types.flattenWithTypeRestrictions && member.kind == Kind.VAR && member.type.isPrimitiveClass()) {
                 return new StaticItem(getFlattenedField(member));
             } else {
                 return new StaticItem(member);
    @@ -161,7 +161,7 @@ Item makeStaticItem(Symbol member) {
          *                      and private members).
          */
         Item makeMemberItem(Symbol member, boolean nonvirtual) {
    -        if (this.types.flattenWithTypeRestrictions && member.kind == Kind.VAR && member.type.isValue()) {
    +        if (this.types.flattenWithTypeRestrictions && member.kind == Kind.VAR && member.type.isPrimitiveClass()) {
                 return new MemberItem(getFlattenedField(member), nonvirtual);
             } else {
                 return new MemberItem(member, nonvirtual);
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java
    index 07c179cb929..32ba0e6ced6 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/PoolWriter.java
    @@ -508,8 +508,8 @@ private Name classSig(Type t) {
             if (typarams.nonEmpty()) {
                 signatureGen.assembleParamsSig(typarams);
             }
    -        signatureGen.assembleSig(t.isValue() ? t.referenceProjection() : types.supertype(t));
    -        if (!t.isValue()) {
    +        signatureGen.assembleSig(t.isPrimitiveClass() ? t.referenceProjection() : types.supertype(t));
    +        if (!t.isPrimitiveClass()) {
                 for (Type i : types.interfaces(t))
                     signatureGen.assembleSig(i);
             }
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/TransValues.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/TransValues.java
    index e8112f0cb0e..a831e6f5c97 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/TransValues.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/TransValues.java
    @@ -364,7 +364,7 @@ public void visitSelect(JCFieldAccess fieldAccess) {
         // Translate a reference style instance creation attempt on a value type to a static factory call.
         @Override
         public void visitNewClass(JCNewClass tree) {
    -        if (types.isValue(tree.clazz.type)) {
    +        if (types.isPrimitiveClass(tree.clazz.type)) {
                 // Enclosing instances or anonymous classes should have been eliminated by now.
                 Assert.check(tree.encl == null && tree.def == null);
                 tree.args = translate(tree.args);
    @@ -385,7 +385,7 @@ public void visitNewClass(JCNewClass tree) {
     
         // Utility methods ...
         private boolean constructingValue() {
    -        return currentClass != null && (currentClass.sym.flags() & Flags.VALUE) != 0 && currentMethod != null && currentMethod.sym.isConstructor();
    +        return currentClass != null && (currentClass.sym.flags() & Flags.PRIMITIVE_CLASS) != 0 && currentMethod != null && currentMethod.sym.isConstructor();
         }
     
         private boolean isInstanceMemberAccess(Symbol symbol) {
    @@ -397,7 +397,7 @@ private boolean isInstanceMemberAccess(Symbol symbol) {
     
         private MethodSymbol getValueFactory(MethodSymbol init) {
             Assert.check(init.name.equals(names.init));
    -        Assert.check(types.isValue(init.owner.type));
    +        Assert.check(types.isPrimitiveClass(init.owner.type));
             MethodSymbol factory = init2factory.get(init);
             if (factory != null)
                 return factory;
    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 c2ecf4b0af6..d7f22f6a7de 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
    @@ -2331,7 +2331,7 @@ JCExpression creator(int newpos, List typeArgs) {
             case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
             case DOUBLE: case BOOLEAN:
                 if (mods.flags != 0) {
    -                long badModifiers = (mods.flags & Flags.VALUE) != 0 ? mods.flags & ~Flags.FINAL : mods.flags;
    +                long badModifiers = (mods.flags & Flags.PRIMITIVE_CLASS) != 0 ? mods.flags & ~Flags.FINAL : mods.flags;
                     log.error(token.pos, Errors.ModNotAllowedHere(asFlagSet(badModifiers)));
                 }
                 if (typeArgs == null) {
    @@ -2402,7 +2402,7 @@ else if (typeArgs != null) {
                 }
                 return e;
             } else if (token.kind == LPAREN) {
    -            long badModifiers = mods.flags & ~(Flags.VALUE | Flags.FINAL);
    +            long badModifiers = mods.flags & ~(Flags.PRIMITIVE_CLASS | Flags.FINAL);
                 if (badModifiers != 0)
                     log.error(token.pos, Errors.ModNotAllowedHere(asFlagSet(badModifiers)));
                 // handle type annotations for instantiations and anonymous classes
    @@ -2411,7 +2411,7 @@ else if (typeArgs != null) {
                 }
                 JCNewClass newClass = classCreatorRest(newpos, null, typeArgs, t, mods.flags);
                 if ((newClass.def == null) && (mods.flags != 0)) {
    -                badModifiers = (mods.flags & Flags.VALUE) != 0 ? mods.flags & ~Flags.FINAL : mods.flags;
    +                badModifiers = (mods.flags & Flags.PRIMITIVE_CLASS) != 0 ? mods.flags & ~Flags.FINAL : mods.flags;
                     log.error(newClass.pos, Errors.ModNotAllowedHere(asFlagSet(badModifiers)));
                 }
                 return newClass;
    @@ -2675,7 +2675,7 @@ List blockStatement() {
             case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
             case ASSERT:
                 return List.of(parseSimpleStatement());
    -        case VALUE:
    +        case PRIMITIVE:
             case MONKEYS_AT:
             case FINAL: {
                 dc = token.comment(CommentStyle.JAVADOC);
    @@ -3210,7 +3210,7 @@ protected JCModifiers modifiersOpt(JCModifiers partial) {
                 case FINAL       : flag = Flags.FINAL; break;
                 case ABSTRACT    : flag = Flags.ABSTRACT; break;
                 case NATIVE      : flag = Flags.NATIVE; break;
    -            case VALUE       : flag = Flags.VALUE; break;
    +            case PRIMITIVE   : flag = Flags.PRIMITIVE_CLASS; break;
                 case VOLATILE    : flag = Flags.VOLATILE; break;
                 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
                 case STRICTFP    : flag = Flags.STRICTFP; break;
    @@ -3243,8 +3243,8 @@ protected JCModifiers modifiersOpt(JCModifiers partial) {
                         if (flags == 0 && annotations.isEmpty())
                             pos = ann.pos;
                         final Name name = TreeInfo.name(ann.annotationType);
    -                    if (name == names.__inline__ || name == names.java_lang___inline__) {
    -                        flag = Flags.VALUE;
    +                    if (name == names.__primitive__ || name == names.java_lang___primitive__) {
    +                        flag = Flags.PRIMITIVE_CLASS;
                         } else {
                             annotations.append(ann);
                             flag = 0;
    @@ -3265,7 +3265,7 @@ protected JCModifiers modifiersOpt(JCModifiers partial) {
                 pos = Position.NOPOS;
     
             // Force value classes to be automatically final.
    -        if ((flags & (Flags.VALUE | Flags.ABSTRACT | Flags.INTERFACE | Flags.ENUM)) == Flags.VALUE) {
    +        if ((flags & (Flags.PRIMITIVE_CLASS | Flags.ABSTRACT | Flags.INTERFACE | Flags.ENUM)) == Flags.PRIMITIVE_CLASS) {
                 flags |= Flags.FINAL;
             }
     
    @@ -3458,9 +3458,9 @@ JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression ty
             return result;
         }
     
    -    // Does the given token signal an inline modifier ? If yes, suitably reclassify token.
    +    // Does the given token signal a primitive modifier ? If yes, suitably reclassify token.
         Token recastToken(Token token) {
    -        if (token.kind != IDENTIFIER || token.name() != names.inline) {
    +        if (token.kind != IDENTIFIER || token.name() != names.primitive) {
                 return token;
             }
             if (peekToken(t->t == PRIVATE ||
    @@ -3488,8 +3488,8 @@ Token recastToken(Token token) {
                              t == INTERFACE ||
                              t == ENUM ||
                              t == IDENTIFIER)) { // new value Comparable() {}
    -            checkSourceLevel(Feature.INLINE_TYPES);
    -            return new Token(VALUE, token.pos, token.endPos, token.comments);
    +            checkSourceLevel(Feature.PRIMITIVE_CLASSES);
    +            return new Token(PRIMITIVE, token.pos, token.endPos, token.comments);
             }
             return token;
         }
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Tokens.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Tokens.java
    index a308a927de8..0d782813f95 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Tokens.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Tokens.java
    @@ -141,7 +141,7 @@ public enum TokenKind implements Formattable, Filter {
             THROWS("throws"),
             TRANSIENT("transient"),
             TRY("try"),
    -        VALUE(), // a phantom token never returned by the scanner, but can result from a reclassification by the parser.
    +        PRIMITIVE(), // a phantom token never returned by the scanner, but can result from a reclassification by the parser.
             VOID("void", Tag.NAMED),
             VOLATILE("volatile"),
             WHILE("while"),
    @@ -246,8 +246,8 @@ public String toString() {
                     return "token.double";
                 case ERROR:
                     return "token.bad-symbol";
    -            case VALUE:
    -                return "value";
    +            case PRIMITIVE:
    +                return "primitive";
                 case EOF:
                     return "token.end-of-input";
                 case DOT: case COMMA: case SEMI: case LPAREN: case RPAREN:
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
    index 39bb746edbc..a8acc27d4f4 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
    @@ -396,10 +396,6 @@ compiler.err.cont.outside.loop=\
     compiler.err.cyclic.inheritance=\
         cyclic inheritance involving {0}
     
    -# 0: symbol
    -compiler.err.cyclic.value.type.membership=\
    -    cyclic inline type membership involving {0}
    -
     # 0: symbol
     compiler.err.cyclic.annotation.element=\
         type of element {0} is cyclic
    @@ -1779,9 +1775,6 @@ compiler.warn.poor.choice.for.module.name=\
     compiler.warn.incubating.modules=\
         using incubating module(s): {0}
     
    -compiler.warn.get.class.compared.with.interface=\
    -    return value of getClass() can never equal the class literal of an interface
    -
     # 0: symbol, 1: symbol
     compiler.warn.has.been.deprecated=\
         {0} in {1} has been deprecated
    @@ -2959,9 +2952,6 @@ compiler.misc.feature.pattern.matching.instanceof=\
     compiler.misc.feature.reifiable.types.instanceof=\
         reifiable types in instanceof
     
    -compiler.misc.feature.inline.type=\
    -    inline type
    -
     compiler.misc.feature.records=\
         records
     
    @@ -3792,61 +3782,71 @@ compiler.err.preview.not.latest=\
     compiler.err.preview.without.source.or.release=\
         --enable-preview must be used with either -source or --release
     
    +compiler.misc.feature.primitive.classes=\
    +    primitive classes
    +
    +# 0: symbol
    +compiler.err.cyclic.primitive.class.membership=\
    +    cyclic primitive class membership involving {0}
    +
    +compiler.warn.get.class.compared.with.interface=\
    +    return value of getClass() can never equal the class literal of an interface
    +
     # 0: name (of method)
    -compiler.err.inline.class.may.not.override=\
    -    Inline classes may not override the method {0} from Object
    +compiler.err.primitive.class.may.not.override=\
    +    primitive classes may not override the method {0} from Object
     
     # 0: name (of method)
    -compiler.err.value.does.not.support=\
    -    Inline types do not support {0}
    +compiler.err.primitive.class.does.not.support=\
    +    primitive classes do not support {0}
     
    -compiler.err.value.may.not.extend=\
    -    Inline type may not extend another inline type or class
    +compiler.err.primitive.class.may.not.extend=\
    +    inappropriate super class declaration for a primitive class
     
    -compiler.err.value.instance.field.expected.here=\
    -    withfield operator requires an instance field of an inline class here
    +compiler.err.primitive.class.instance.field.expected.here=\
    +    withfield operator requires an instance field of a primitive class here
     
     compiler.err.with.field.operator.disallowed=\
         WithField operator is allowed only with -XDallowWithFieldOperator
     
     compiler.err.this.exposed.prematurely=\
    -    Inine type instance should not be passed around before being fully initialized
    +    primitive class instance should not be passed around before being fully initialized
     
     # 0: type
    -compiler.err.generic.parameterization.with.value.type=\
    -    Inferred type {0} involves generic parameterization by an inline type
    +compiler.err.generic.parameterization.with.primitive.class=\
    +    Inferred type {0} involves generic parameterization by a primitive class
     
     # 0: type
    -compiler.err.inline.type.must.not.implement.identity.object=\
    -    The inline type {0} attempts to implement the incompatible interface IdentityObject
    +compiler.err.primitive.class.must.not.implement.identity.object=\
    +    The primitive class {0} attempts to implement the incompatible interface IdentityObject
     
     # 0: symbol, 1: type
    -compiler.err.concrete.supertype.for.inline.class=\
    -    The concrete class {1} is not allowed to be a super class of the inline class {0} either directly or indirectly
    +compiler.err.concrete.supertype.for.primitive.class=\
    +    The concrete class {1} is not allowed to be a super class of the primitive class {0} either directly or indirectly
     
     # 0: symbol, 1: symbol, 2: type
     compiler.err.super.method.cannot.be.synchronized=\
    -    The method {0} in the super class {2} of the inline type {1} is synchronized. This is disallowed
    +    The method {0} in the super class {2} of the primitive class {1} is synchronized. This is disallowed
     
     # 0: symbol, 1: symbol, 2: type
     compiler.err.super.constructor.cannot.take.arguments=\
    -    The super class {2} of the inline type {1} defines a constructor {0} that takes arguments. This is disallowed
    +    The super class {2} of the primitive class {1} defines a constructor {0} that takes arguments. This is disallowed
     
     # 0: symbol, 1: symbol, 2: type
     compiler.err.super.field.not.allowed=\
    -    The super class {2} of the inline type {1} defines an instance field {0}. This is disallowed
    +    The super class {2} of the primitive class {1} defines an instance field {0}. This is disallowed
     
     # 0: symbol, 1: symbol, 2: type
     compiler.err.super.no.arg.constructor.must.be.empty=\
    -    The super class {2} of the inline type {1} defines a nonempty no-arg constructor {0}. This is disallowed
    +    The super class {2} of the primitive class {1} defines a nonempty no-arg constructor {0}. This is disallowed
     
     # 0: symbol, 1: type
     compiler.err.super.class.declares.init.block=\
    -    The super class {1} of the inline class {0} declares one or more non-empty instance initializer blocks. This is disallowed.
    +    The super class {1} of the primitive class {0} declares one or more non-empty instance initializer blocks. This is disallowed.
     
     # 0: symbol, 1: type
     compiler.err.super.class.cannot.be.inner=\
    -    The super class {1} of the inline class {0} is an inner class. This is disallowed.
    +    The super class {1} of the primitive class {0} is an inner class. This is disallowed.
     
     compiler.err.projection.cant.be.instantiated=\
         Illegal attempt to instantiate a projection type
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
    index 169c0a861a7..0d293b61394 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
    @@ -100,7 +100,7 @@ public static Names instance(Context context) {
         public final Name serialVersionUID;
         public final Name toString;
         public final Name value;
    -    public final Name inline;
    +    public final Name primitive;
         public final Name valueOf;
         public final Name values;
         public final Name readResolve;
    @@ -113,8 +113,8 @@ public static Names instance(Context context) {
         public final Name java_lang_Enum;
         public final Name java_lang_Object;
         public final Name java_lang_System;
    -    public final Name __inline__;
    -    public final Name java_lang___inline__;
    +    public final Name __primitive__;
    +    public final Name java_lang___primitive__;
         public final Name java_lang_IdentityObject;
     
         // names of builtin classes
    @@ -287,7 +287,7 @@ public Names(Context context) {
             serialVersionUID = fromString("serialVersionUID");
             toString = fromString("toString");
             value = fromString("value");
    -        inline = fromString("inline");
    +        primitive = fromString("primitive");
             valueOf = fromString("valueOf");
             values = fromString("values");
             readResolve = fromString("readResolve");
    @@ -301,8 +301,8 @@ public Names(Context context) {
             java_lang_Enum = fromString("java.lang.Enum");
             java_lang_Object = fromString("java.lang.Object");
             java_lang_System = fromString("java.lang.System");
    -        __inline__ = fromString("__inline__");
    -        java_lang___inline__ = fromString("java.lang.__inline__");
    +        __primitive__ = fromString("__primitive__");
    +        java_lang___primitive__ = fromString("java.lang.__primitive__");
             java_lang_IdentityObject = fromString("java.lang.IdentityObject");
     
             // names of builtin classes
    diff --git a/src/jdk.compiler/share/man/javac.1 b/src/jdk.compiler/share/man/javac.1
    index 1e2b536b35a..8782020547a 100644
    --- a/src/jdk.compiler/share/man/javac.1
    +++ b/src/jdk.compiler/share/man/javac.1
    @@ -21,7 +21,7 @@
     .\"
     .\" Automatically generated by Pandoc 2.3.1
     .\"
    -.TH "JAVAC" "1" "2020" "JDK 16" "JDK Commands"
    +.TH "JAVAC" "1" "2021" "JDK 17\-ea" "JDK Commands"
     .hy
     .SH NAME
     .PP
    @@ -631,11 +631,6 @@ As applicable, see the descriptions in \f[B]\f[BC]\-\-release\f[B]\f[R],
     details.
     .RE
     .TP
    -.B \f[CB]\-\-doclint\-format\f[R] [\f[CB]html4\f[R]|\f[CB]html5\f[R]]
    -Specifies the format for documentation comments.
    -.RS
    -.RE
    -.TP
     .B \f[CB]\-\-patch\-module\f[R] \f[I]module\f[R]\f[CB]=\f[R]\f[I]path\f[R]
     Overrides or augments a module with classes and resources in JAR files
     or directories.
    diff --git a/src/jdk.compiler/share/man/serialver.1 b/src/jdk.compiler/share/man/serialver.1
    index 140b940aad6..c1ec3ebcee6 100644
    --- a/src/jdk.compiler/share/man/serialver.1
    +++ b/src/jdk.compiler/share/man/serialver.1
    @@ -21,7 +21,7 @@
     .\"
     .\" Automatically generated by Pandoc 2.3.1
     .\"
    -.TH "SERIALVER" "1" "2020" "JDK 16" "JDK Commands"
    +.TH "SERIALVER" "1" "2021" "JDK 17\-ea" "JDK Commands"
     .hy
     .SH NAME
     .PP
    diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/BiClassValue.java b/src/jdk.dynalink/share/classes/jdk/dynalink/BiClassValue.java
    new file mode 100644
    index 00000000000..6396676eabe
    --- /dev/null
    +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/BiClassValue.java
    @@ -0,0 +1,219 @@
    +/*
    + * 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.dynalink;
    +
    +import java.lang.invoke.MethodHandles;
    +import java.lang.invoke.VarHandle;
    +import java.security.AccessControlContext;
    +import java.security.AccessController;
    +import java.security.PrivilegedAction;
    +import java.util.Map;
    +import java.util.Objects;
    +import java.util.function.BiFunction;
    +import java.util.function.Function;
    +import jdk.dynalink.internal.AccessControlContextFactory;
    +
    +import static jdk.dynalink.internal.InternalTypeUtilities.canReferenceDirectly;
    +
    +/**
    + * Similar to ClassValue, but lazily associates a computed value with
    + * (potentially) every pair of types.
    + * @param  the value to associate with pairs of types.
    + */
    +final class BiClassValue {
    +    /**
    +     * Creates a new BiClassValue that uses the specified binary function to
    +     * lazily compute the values.
    +     * @param compute the binary function to compute the values. Ordinarily, it
    +     *                is invoked at most once for any pair of values. However,
    +     *                it is possible for it to be invoked concurrently. It can
    +     *                even be invoked concurrently multiple times for the same
    +     *                arguments under contention. In that case, it is undefined
    +     *                which of the computed values will be retained therefore
    +     *                returning semantically equivalent values is strongly
    +     *                recommended; the function should ideally be pure.
    +     *                Additionally, if the pair of types passed as parameters
    +     *                are from unrelated class loaders, the computed value is
    +     *                not cached at all and the function might be reinvoked
    +     *                with the same parameters in the future. Finally, a null
    +     *                return value is allowed, but not cached.
    +     * @param  the type of the values
    +     * @return a new BiClassValue that computes the values using the passed
    +     * function.
    +     */
    +    static  BiClassValue computing(final BiFunction, Class, T> compute) {
    +        return new BiClassValue<>(compute);
    +    }
    +
    +    /**
    +     * A type-specific map that stores the values specific to pairs of types
    +     * which include its class in one of the positions of the pair. Internally,
    +     * it uses at most two maps named "forward" and "reverse". A BiClassValues
    +     * for class C1 can store values for (C1, Cy) in its forward map as well
    +     * as values for (Cx, C1) in its reverse map. The reason for this scheme
    +     * is to avoid creating unwanted strong references from a parent class
    +     * loader to a child class loader. If for a pair of classes (C1, C2)
    +     * either C1 and C2 are in the same class loader, or C2 is in parent of C1,
    +     * or C2 is a system class, forward map of C1's BiClassValues is used for
    +     * storing the computed value. If C1 is in parent of C2, or C1 is a system
    +     * class, reverse map of C2's BiClassValues is used for storing. If the
    +     * class loaders are unrelated, the computed value is not cached and will
    +     * be recomputed on every evaluation.
    +     * NOTE that while every instance of this class is type-specific, it does
    +     * not store a reference to the type Class object itself. BiClassValuesRoot
    +     * creates the association from a type Class object to its BiClassValues'.
    +     * @param  the type of the values
    +     */
    +    private final static class BiClassValues {
    +        // These will be used for compareAndExchange on forward and reverse fields.
    +        private static final VarHandle FORWARD;
    +        private static final VarHandle REVERSE;
    +        static {
    +            final MethodHandles.Lookup lookup = MethodHandles.lookup();
    +            try {
    +                FORWARD = lookup.findVarHandle(BiClassValues.class, "forward", Map.class);
    +                REVERSE = lookup.findVarHandle(BiClassValues.class, "reverse", Map.class);
    +            } catch (NoSuchFieldException | IllegalAccessException e) {
    +                throw new AssertionError(e);
    +            }
    +        }
    +
    +        private Map, T> forward = Map.of();
    +        private Map, T> reverse = Map.of();
    +
    +        T getForwardValue(final Class c) {
    +            return forward.get(c);
    +        }
    +
    +        T getReverseValue(final Class c) {
    +            return reverse.get(c);
    +        }
    +
    +        private T compute(final VarHandle mapHandle, final Class c, final Function, T> compute) {
    +            @SuppressWarnings("unchecked")
    +            Map, T> map = (Map, T>) mapHandle.getVolatile(this);
    +            T value;
    +            T newValue = null;
    +            while ((value = map.get(c)) == null) {
    +                if (newValue == null) {
    +                    newValue = compute.apply(c);
    +                    if (newValue == null) {
    +                        break;
    +                    }
    +                }
    +                @SuppressWarnings({"unchecked", "rawtypes"})
    +                final Map.Entry, T>[] entries = map.entrySet().toArray(new Map.Entry[map.size() + 1]);
    +                entries[map.size()] = Map.entry(c, newValue);
    +                final var newMap = Map.ofEntries(entries);
    +                @SuppressWarnings("unchecked")
    +                final var witness = (Map, T>) mapHandle.compareAndExchange(this, map, newMap);
    +                if (witness == map) {
    +                    value = newValue;
    +                    break;
    +                }
    +                map = witness;
    +            }
    +            return value;
    +        }
    +
    +        T computeForward(final Class c, Function, T> compute) {
    +            return compute(FORWARD, c, compute);
    +        }
    +
    +        T computeReverse(final Class c, Function, T> compute) {
    +            return compute(REVERSE, c, compute);
    +        }
    +    }
    +
    +    // A named class used for "root" field so it can be static so it doesn't
    +    // gain a synthetic this$0 reference as that'd cause a memory leak through
    +    // unwanted anchoring to a GC root when used with system classes.
    +    private static final class BiClassValuesRoot extends ClassValue> {
    +        @Override protected BiClassValues computeValue(Class type) {
    +            return new BiClassValues<>();
    +        }
    +    }
    +
    +    private enum RetentionDirection {
    +        FORWARD,
    +        REVERSE,
    +        NEITHER
    +    }
    +
    +    private final BiClassValuesRoot root = new BiClassValuesRoot<>();
    +    private final BiFunction, Class, T> compute;
    +
    +    private BiClassValue(final BiFunction, Class, T> compute) {
    +        this.compute = Objects.requireNonNull(compute);
    +    }
    +
    +    final T get(final Class c1, final Class c2) {
    +        // Most likely case: it is in the forward map of c1's BiClassValues
    +        final BiClassValues cv1 = root.get(c1);
    +        final T v1 = cv1.getForwardValue(c2);
    +        if (v1 != null) {
    +            return v1;
    +        }
    +
    +        // Next likely case: it is in the reverse map of c2's BiClassValues
    +        final BiClassValues cv2 = root.get(c2);
    +        final T v2 = cv2.getReverseValue(c1);
    +        if (v2 != null) {
    +            return v2;
    +        }
    +
    +        // Value is uncached, compute it and cache if possible.
    +        switch (getRetentionDirection(c1, c2)) {
    +            case FORWARD:
    +                // loader of c1 can see loader of c2, store value for (c1, c2) in cv1's forward map
    +                return cv1.computeForward(c2, cy -> compute.apply(c1, cy));
    +            case REVERSE:
    +                // loader of c2 can see loader of c1, store value for (c1, c2) in cv2's reverse map
    +                return cv2.computeReverse(c1, cx -> compute.apply(cx, c2));
    +            case NEITHER:
    +                // Class loaders are unrelated; compute and return uncached.
    +                return compute.apply(c1, c2);
    +            default:
    +                throw new AssertionError(); // enum values exhausted
    +        }
    +    }
    +
    +    private static final AccessControlContext GET_CLASS_LOADER_CONTEXT =
    +        AccessControlContextFactory.createAccessControlContext("getClassLoader");
    +
    +    private static RetentionDirection getRetentionDirection(Class from, Class to) {
    +        return AccessController.doPrivileged((PrivilegedAction) () -> {
    +            final ClassLoader cl1 = from.getClassLoader();
    +            final ClassLoader cl2 = to.getClassLoader();
    +            if (canReferenceDirectly(cl1, cl2)) {
    +                return RetentionDirection.FORWARD;
    +            } else if (canReferenceDirectly(cl2, cl1)) {
    +                return RetentionDirection.REVERSE;
    +            }
    +            return RetentionDirection.NEITHER;
    +        }, GET_CLASS_LOADER_CONTEXT);
    +    }
    +}
    diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/ClassMap.java b/src/jdk.dynalink/share/classes/jdk/dynalink/ClassMap.java
    deleted file mode 100644
    index f03e8db3492..00000000000
    --- a/src/jdk.dynalink/share/classes/jdk/dynalink/ClassMap.java
    +++ /dev/null
    @@ -1,157 +0,0 @@
    -/*
    - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
    - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    - *
    - * This code is free software; you can redistribute it and/or modify it
    - * under the terms of the GNU General Public License version 2 only, as
    - * published by the Free Software Foundation.  Oracle designates this
    - * particular file as subject to the "Classpath" exception as provided
    - * by Oracle in the LICENSE file that accompanied this code.
    - *
    - * This code is distributed in the hope that it will be useful, but WITHOUT
    - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    - * version 2 for more details (a copy is included in the LICENSE file that
    - * accompanied this code).
    - *
    - * You should have received a copy of the GNU General Public License version
    - * 2 along with this work; if not, write to the Free Software Foundation,
    - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    - *
    - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    - * or visit www.oracle.com if you need additional information or have any
    - * questions.
    - */
    -
    -/*
    - * This file is available under and governed by the GNU General Public
    - * License version 2 only, as published by the Free Software Foundation.
    - * However, the following notice accompanied the original version of this
    - * file, and Oracle licenses the original version of this file under the BSD
    - * license:
    - */
    -/*
    -   Copyright 2009-2013 Attila Szegedi
    -
    -   Redistribution and use in source and binary forms, with or without
    -   modification, are permitted provided that the following conditions are
    -   met:
    -   * Redistributions of source code must retain the above copyright
    -     notice, this list of conditions and the following disclaimer.
    -   * Redistributions in binary form must reproduce the above copyright
    -     notice, this list of conditions and the following disclaimer in the
    -     documentation and/or other materials provided with the distribution.
    -   * Neither the name of the copyright holder nor the names of
    -     contributors may be used to endorse or promote products derived from
    -     this software without specific prior written permission.
    -
    -   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
    -   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
    -   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
    -   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
    -   BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    -   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    -   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
    -   BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    -   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    -   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
    -   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    -*/
    -
    -package jdk.dynalink;
    -
    -import java.lang.ref.Reference;
    -import java.lang.ref.SoftReference;
    -import java.security.AccessControlContext;
    -import java.security.AccessController;
    -import java.security.PrivilegedAction;
    -import java.util.Map;
    -import java.util.WeakHashMap;
    -import java.util.concurrent.ConcurrentHashMap;
    -import java.util.concurrent.ConcurrentMap;
    -import jdk.dynalink.internal.AccessControlContextFactory;
    -import jdk.dynalink.internal.InternalTypeUtilities;
    -
    -/**
    - * A dual map that can either strongly or weakly reference a given class depending on whether the class is visible from
    - * a class loader or not.
    - *
    - * @param  the type of the values in the map
    - */
    -abstract class ClassMap {
    -    private static final AccessControlContext GET_CLASS_LOADER_CONTEXT =
    -            AccessControlContextFactory.createAccessControlContext("getClassLoader");
    -
    -    private final ConcurrentMap, T> map = new ConcurrentHashMap<>();
    -    private final Map, Reference> weakMap = new WeakHashMap<>();
    -    private final ClassLoader classLoader;
    -
    -    /**
    -     * Creates a new class map. It will use strong references for all keys and values where the key is a class visible
    -     * from the class loader, and will use weak keys and soft values for all other classes.
    -     *
    -     * @param classLoader the classloader that determines strong referenceability.
    -     */
    -    ClassMap(final ClassLoader classLoader) {
    -        this.classLoader = classLoader;
    -    }
    -
    -    /**
    -     * Compute the value associated with the given class. It is possible that the method will be invoked several times
    -     * (or even concurrently) for the same class parameter.
    -     *
    -     * @param clazz the class to compute the value for
    -     * @return the return value. Must not be null.
    -     */
    -    abstract T computeValue(Class clazz);
    -
    -    /**
    -     * Returns the value associated with the class
    -     *
    -     * @param clazz the class
    -     * @return the value associated with the class
    -     */
    -    T get(final Class clazz) {
    -        // Check in fastest first - objects we're allowed to strongly reference
    -        final T v = map.get(clazz);
    -        if(v != null) {
    -            return v;
    -        }
    -        // Check objects we're not allowed to strongly reference
    -        Reference ref;
    -        synchronized(weakMap) {
    -            ref = weakMap.get(clazz);
    -        }
    -        if(ref != null) {
    -            final T refv = ref.get();
    -            if(refv != null) {
    -                return refv;
    -            }
    -        }
    -        // Not found in either place; create a new value
    -        final T newV = computeValue(clazz);
    -        assert newV != null;
    -
    -        final Boolean canReferenceDirectly = AccessController.doPrivileged(
    -            (PrivilegedAction) () -> InternalTypeUtilities.canReferenceDirectly(classLoader, clazz.getClassLoader()),
    -            GET_CLASS_LOADER_CONTEXT);
    -
    -        // If allowed to strongly reference, put it in the fast map
    -        if(canReferenceDirectly) {
    -            final T oldV = map.putIfAbsent(clazz, newV);
    -            return oldV != null ? oldV : newV;
    -        }
    -        // Otherwise, put it into the weak map
    -        synchronized(weakMap) {
    -            ref = weakMap.get(clazz);
    -            if(ref != null) {
    -                final T oldV = ref.get();
    -                if(oldV != null) {
    -                    return oldV;
    -                }
    -            }
    -            weakMap.put(clazz, new SoftReference<>(newV));
    -            return newV;
    -        }
    -    }
    -}
    diff --git a/src/jdk.dynalink/share/classes/jdk/dynalink/TypeConverterFactory.java b/src/jdk.dynalink/share/classes/jdk/dynalink/TypeConverterFactory.java
    index 90e9305077f..97ad72b309e 100644
    --- a/src/jdk.dynalink/share/classes/jdk/dynalink/TypeConverterFactory.java
    +++ b/src/jdk.dynalink/share/classes/jdk/dynalink/TypeConverterFactory.java
    @@ -65,13 +65,9 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     import java.lang.invoke.MethodHandles.Lookup;
     import java.lang.invoke.MethodType;
     import java.lang.invoke.WrongMethodTypeException;
    -import java.security.AccessControlContext;
    -import java.security.AccessController;
    -import java.security.PrivilegedAction;
     import java.util.LinkedList;
     import java.util.List;
     import java.util.function.Supplier;
    -import jdk.dynalink.internal.AccessControlContextFactory;
     import jdk.dynalink.linker.ConversionComparator;
     import jdk.dynalink.linker.ConversionComparator.Comparison;
     import jdk.dynalink.linker.GuardedInvocation;
    @@ -86,70 +82,12 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      * instances and creates appropriate converters for method handles.
      */
     final class TypeConverterFactory {
    -    private static final AccessControlContext GET_CLASS_LOADER_CONTEXT =
    -            AccessControlContextFactory.createAccessControlContext("getClassLoader");
    -
    -    private final GuardingTypeConverterFactory[] factories;
         private final ConversionComparator[] comparators;
         private final MethodTypeConversionStrategy autoConversionStrategy;
     
    -    private final ClassValue> converterMap = new ClassValue<>() {
    -        @Override
    -        protected ClassMap computeValue(final Class sourceType) {
    -            return new ClassMap<>(getClassLoader(sourceType)) {
    -                @Override
    -                protected MethodHandle computeValue(final Class targetType) {
    -                    try {
    -                        return createConverter(sourceType, targetType);
    -                    } catch (final RuntimeException e) {
    -                        throw e;
    -                    } catch (final Exception e) {
    -                        throw new RuntimeException(e);
    -                    }
    -                }
    -            };
    -        }
    -    };
    -
    -    private final ClassValue> converterIdentityMap = new ClassValue<>() {
    -        @Override
    -        protected ClassMap computeValue(final Class sourceType) {
    -            return new ClassMap<>(getClassLoader(sourceType)) {
    -                @Override
    -                protected MethodHandle computeValue(final Class targetType) {
    -                    if(!canAutoConvert(sourceType, targetType)) {
    -                        final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType);
    -                        if(converter != IDENTITY_CONVERSION) {
    -                            return converter;
    -                        }
    -                    }
    -                    return IDENTITY_CONVERSION.asType(MethodType.methodType(targetType, sourceType));
    -                }
    -            };
    -        }
    -    };
    -
    -    private final ClassValue> canConvert = new ClassValue<>() {
    -        @Override
    -        protected ClassMap computeValue(final Class sourceType) {
    -            return new ClassMap<>(getClassLoader(sourceType)) {
    -                @Override
    -                protected Boolean computeValue(final Class targetType) {
    -                    try {
    -                        return getTypeConverterNull(sourceType, targetType) != null;
    -                    } catch (final RuntimeException e) {
    -                        throw e;
    -                    } catch (final Exception e) {
    -                        throw new RuntimeException(e);
    -                    }
    -                }
    -            };
    -        }
    -    };
    -
    -    private static ClassLoader getClassLoader(final Class clazz) {
    -        return AccessController.doPrivileged((PrivilegedAction) clazz::getClassLoader, GET_CLASS_LOADER_CONTEXT);
    -    }
    +    private final BiClassValue converterMap;
    +    private final BiClassValue converterIdentityMap;
    +    private final BiClassValue canConvert;
     
         /**
          * Creates a new type converter factory from the available {@link GuardingTypeConverterFactory} instances.
    @@ -181,9 +119,27 @@ private static ClassLoader getClassLoader(final Class clazz) {
                     c.add((ConversionComparator)factory);
                 }
             }
    -        this.factories = l.toArray(new GuardingTypeConverterFactory[0]);
             this.comparators = c.toArray(new ConversionComparator[0]);
             this.autoConversionStrategy = autoConversionStrategy;
    +
    +        final GuardingTypeConverterFactory[] afactories = l.toArray(new GuardingTypeConverterFactory[0]);
    +        final BiClassValue converterMap = BiClassValue.computing(
    +            (sourceType, targetType) -> createConverter(sourceType, targetType, afactories));
    +
    +        converterIdentityMap = BiClassValue.computing((sourceType, targetType) -> {
    +            if(!canAutoConvert(sourceType, targetType)) {
    +                final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType, converterMap);
    +                if(converter != IDENTITY_CONVERSION) {
    +                    return converter;
    +                }
    +            }
    +            return IDENTITY_CONVERSION.asType(MethodType.methodType(targetType, sourceType));
    +        });
    +
    +        canConvert = BiClassValue.computing(
    +            (sourceType, targetType) -> getTypeConverterNull(sourceType, targetType, converterMap) != null);
    +
    +        this.converterMap = converterMap;
         }
     
         /**
    @@ -219,7 +175,7 @@ MethodHandle asType(final MethodHandle handle, final MethodType fromType) {
                 if(canAutoConvert(fromParamType, toParamType)) {
                     newHandle = applyConverters(newHandle, pos, converters);
                 } else {
    -                final MethodHandle converter = getTypeConverterNull(fromParamType, toParamType);
    +                final MethodHandle converter = getTypeConverterNull(fromParamType, toParamType, converterMap);
                     if(converter != null) {
                         if(converters.isEmpty()) {
                             pos = i;
    @@ -237,7 +193,7 @@ MethodHandle asType(final MethodHandle handle, final MethodType fromType) {
             final Class toRetType = toType.returnType();
             if(fromRetType != Void.TYPE && toRetType != Void.TYPE) {
                 if(!canAutoConvert(toRetType, fromRetType)) {
    -                final MethodHandle converter = getTypeConverterNull(toRetType, fromRetType);
    +                final MethodHandle converter = getTypeConverterNull(toRetType, fromRetType, converterMap);
                     if(converter != null) {
                         newHandle = MethodHandles.filterReturnValue(newHandle, converter);
                     }
    @@ -274,7 +230,7 @@ private static MethodHandle applyConverters(final MethodHandle handle, final int
          * @return true if there can be a conversion, false if there can not.
          */
         boolean canConvert(final Class from, final Class to) {
    -        return canAutoConvert(from, to) || canConvert.get(from).get(to);
    +        return canAutoConvert(from, to) || canConvert.get(from, to);
         }
     
         /**
    @@ -315,21 +271,21 @@ Comparison compareConversion(final Class sourceType, final Class targetTyp
             return TypeUtilities.isMethodInvocationConvertible(fromType, toType);
         }
     
    -    /*private*/ MethodHandle getCacheableTypeConverterNull(final Class sourceType, final Class targetType) {
    -        final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType);
    +    /*private*/ static MethodHandle getCacheableTypeConverterNull(final Class sourceType, final Class targetType, final BiClassValue converterMap) {
    +        final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType, converterMap);
             return converter == IDENTITY_CONVERSION ? null : converter;
         }
     
    -    /*private*/ MethodHandle getTypeConverterNull(final Class sourceType, final Class targetType) {
    +    /*private*/ static MethodHandle getTypeConverterNull(final Class sourceType, final Class targetType, final BiClassValue converterMap) {
             try {
    -            return getCacheableTypeConverterNull(sourceType, targetType);
    +            return getCacheableTypeConverterNull(sourceType, targetType, converterMap);
             } catch(final NotCacheableConverter e) {
                 return e.converter;
             }
         }
     
    -    /*private*/ MethodHandle getCacheableTypeConverter(final Class sourceType, final Class targetType) {
    -        return converterMap.get(sourceType).get(targetType);
    +    /*private*/ static MethodHandle getCacheableTypeConverter(final Class sourceType, final Class targetType, final BiClassValue converterMap) {
    +        return converterMap.get(sourceType, targetType);
         }
     
         /**
    @@ -343,7 +299,7 @@ Comparison compareConversion(final Class sourceType, final Class targetTyp
          */
         MethodHandle getTypeConverter(final Class sourceType, final Class targetType) {
             try {
    -            return converterIdentityMap.get(sourceType).get(targetType);
    +            return converterIdentityMap.get(sourceType, targetType);
             } catch(final NotCacheableConverter e) {
                 return e.converter;
             }
    @@ -366,7 +322,7 @@ public Lookup get() {
             }
         }
     
    -    /*private*/ MethodHandle createConverter(final Class sourceType, final Class targetType) throws Exception {
    +    /*private*/ static MethodHandle createConverter(final Class sourceType, final Class targetType, GuardingTypeConverterFactory[] factories) {
             final MethodType type = MethodType.methodType(targetType, sourceType);
             final MethodHandle identity = IDENTITY_CONVERSION.asType(type);
             MethodHandle last = identity;
    @@ -379,6 +335,10 @@ public Lookup get() {
                         last = next.compose(last);
                     }
                 }
    +        } catch (final RuntimeException e) {
    +            throw e;
    +        } catch (final Exception e) {
    +            throw new RuntimeException(e);
             } finally {
                 lookupSupplier.closed = true;
             }
    diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp
    index ca8b6208019..529a8aef80d 100644
    --- a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp
    +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
      * Copyright (c) 2019, 2020, NTT DATA.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
    @@ -183,6 +183,8 @@ static void fillThreadsAndLoadObjects(JNIEnv* env, jobject this_obj, struct ps_p
         CHECK_EXCEPTION;
         env->CallBooleanMethod(threadList, listAdd_ID, thread);
         CHECK_EXCEPTION;
    +    env->DeleteLocalRef(thread);
    +    env->DeleteLocalRef(threadList);
       }
     
       // add load objects
    @@ -205,6 +207,9 @@ static void fillThreadsAndLoadObjects(JNIEnv* env, jobject this_obj, struct ps_p
          CHECK_EXCEPTION;
          env->CallBooleanMethod(loadObjectList, listAdd_ID, loadObject);
          CHECK_EXCEPTION;
    +     env->DeleteLocalRef(str);
    +     env->DeleteLocalRef(loadObject);
    +     env->DeleteLocalRef(loadObjectList);
       }
     }
     
    diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c
    index 4087d1c0f71..9f7c4050ef2 100644
    --- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c
    +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -455,13 +455,15 @@ static bool read_interp_segments(struct ps_prochandle* ph) {
     }
     
     // process segments of a a.out
    -static bool read_exec_segments(struct ps_prochandle* ph, ELF_EHDR* exec_ehdr) {
    +// returns base address of executable.
    +static uintptr_t read_exec_segments(struct ps_prochandle* ph, ELF_EHDR* exec_ehdr) {
       int i = 0;
       ELF_PHDR* phbuf = NULL;
       ELF_PHDR* exec_php = NULL;
    +  uintptr_t result = 0L;
     
       if ((phbuf = read_program_header_table(ph->core->exec_fd, exec_ehdr)) == NULL) {
    -    return false;
    +    return 0L;
       }
     
       for (exec_php = phbuf, i = 0; i < exec_ehdr->e_phnum; i++) {
    @@ -502,10 +504,14 @@ static bool read_exec_segments(struct ps_prochandle* ph, ELF_EHDR* exec_ehdr) {
         // from PT_DYNAMIC we want to read address of first link_map addr
         case PT_DYNAMIC: {
           if (exec_ehdr->e_type == ET_EXEC) {
    +        result = exec_php->p_vaddr;
             ph->core->dynamic_addr = exec_php->p_vaddr;
           } else { // ET_DYN
    +        // Base address of executable is based on entry point (AT_ENTRY).
    +        result = ph->core->dynamic_addr - exec_ehdr->e_entry;
    +
             // dynamic_addr has entry point of executable.
    -        // Thus we should substract it.
    +        // Thus we should subtract it.
             ph->core->dynamic_addr += exec_php->p_vaddr - exec_ehdr->e_entry;
           }
           print_debug("address of _DYNAMIC is 0x%lx\n", ph->core->dynamic_addr);
    @@ -517,10 +523,10 @@ static bool read_exec_segments(struct ps_prochandle* ph, ELF_EHDR* exec_ehdr) {
       } // for
     
       free(phbuf);
    -  return true;
    +  return result;
      err:
       free(phbuf);
    -  return false;
    +  return 0L;
     }
     
     
    @@ -772,14 +778,12 @@ Pgrab_core(const char* exec_file, const char* core_file) {
       }
     
       // process exec file segments
    -  if (read_exec_segments(ph, &exec_ehdr) != true) {
    +  uintptr_t exec_base_addr = read_exec_segments(ph, &exec_ehdr);
    +  if (exec_base_addr == 0L) {
         goto err;
       }
    -
    -  // exec file is also treated like a shared object for symbol search
    -  // FIXME: This is broken and ends up with a base address of 0. See JDK-8248876.
    -  if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd,
    -                      (uintptr_t)0 + find_base_address(ph->core->exec_fd, &exec_ehdr)) == NULL) {
    +  print_debug("exec_base_addr = 0x%lx\n", exec_base_addr);
    +  if (add_lib_info_fd(ph, exec_file, ph->core->exec_fd, exec_base_addr) == NULL) {
         goto err;
       }
     
    diff --git a/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m b/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m
    index cfbf7f9b787..b1587f3d51a 100644
    --- a/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m
    +++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -24,8 +24,6 @@
     
     #include 
     #import 
    -#import 
    -#import 
     
     #include 
     
    @@ -260,6 +258,39 @@ jlong lookupByNameIncore(
       return addr;
     }
     
    +/* Create a pool and initiate a try block to catch any exception */
    +#define JNI_COCOA_ENTER(env) \
    + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; \
    + @try {
    +
    +/* Don't allow NSExceptions to escape to Java.
    + * If there is a Java exception that has been thrown that should escape.
    + * And ensure we drain the auto-release pool.
    + */
    +#define JNI_COCOA_EXIT(env) \
    + } \
    + @catch (NSException *e) { \
    +     NSLog(@"%@", [e callStackSymbols]); \
    + } \
    + @finally { \
    +    [pool drain]; \
    + };
    +
    +static NSString* JavaStringToNSString(JNIEnv *env, jstring jstr) {
    +
    +    if (jstr == NULL) {
    +        return NULL;
    +    }
    +    jsize len = (*env)->GetStringLength(env, jstr);
    +    const jchar *chars = (*env)->GetStringChars(env, jstr, NULL);
    +    if (chars == NULL) {
    +        return NULL;
    +    }
    +    NSString *result = [NSString stringWithCharacters:(UniChar *)chars length:len];
    +    (*env)->ReleaseStringChars(env, jstr, chars);
    +    return result;
    +}
    +
     /*
      * Class:     sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal
      * Method:    lookupByName0
    @@ -277,8 +308,9 @@ jlong lookupByNameIncore(
     
       jlong address = 0;
     
    -JNF_COCOA_ENTER(env);
    -  NSString *symbolNameString = JNFJavaToNSString(env, symbolName);
    +  JNI_COCOA_ENTER(env);
    +
    +  NSString *symbolNameString = JavaStringToNSString(env, symbolName);
     
       print_debug("lookupInProcess called for %s\n", [symbolNameString UTF8String]);
     
    @@ -289,7 +321,7 @@ jlong lookupByNameIncore(
       }
     
       print_debug("address of symbol %s = %llx\n", [symbolNameString UTF8String], address);
    -JNF_COCOA_EXIT(env);
    +  JNI_COCOA_EXIT(env);
     
       return address;
     }
    @@ -812,7 +844,7 @@ static bool wait_for_exception() {
     {
       print_debug("attach0 called for jpid=%d\n", (int)jpid);
     
    -JNF_COCOA_ENTER(env);
    +  JNI_COCOA_ENTER(env);
     
       kern_return_t result;
       task_t gTask = 0;
    @@ -926,13 +958,17 @@ static bool wait_for_exception() {
         THROW_NEW_DEBUGGER_EXCEPTION("Can't attach symbolicator to the process");
       }
     
    -JNF_COCOA_EXIT(env);
    +  JNI_COCOA_EXIT(env);
     }
     
     /** For core file,
         called from Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__Ljava_lang_String_2Ljava_lang_String_2 */
     static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle* ph) {
       int n = 0, i = 0;
    +  jobject loadObjectList;
    +
    +  loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
    +  CHECK_EXCEPTION;
     
       // add load objects
       n = get_num_libs(ph);
    @@ -940,7 +976,6 @@ static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle*
          uintptr_t base;
          const char* name;
          jobject loadObject;
    -     jobject loadObjectList;
          jstring nameString;
     
          base = get_lib_base(ph, i);
    @@ -950,10 +985,10 @@ static void fillLoadObjects(JNIEnv* env, jobject this_obj, struct ps_prochandle*
          loadObject = (*env)->CallObjectMethod(env, this_obj, createLoadObject_ID,
                                                 nameString, (jlong)0, (jlong)base);
          CHECK_EXCEPTION;
    -     loadObjectList = (*env)->GetObjectField(env, this_obj, loadObjectList_ID);
    -     CHECK_EXCEPTION;
          (*env)->CallBooleanMethod(env, loadObjectList, listAdd_ID, loadObject);
          CHECK_EXCEPTION;
    +     (*env)->DeleteLocalRef(env, nameString);
    +     (*env)->DeleteLocalRef(env, loadObject);
       }
     }
     
    @@ -1020,7 +1055,8 @@ static void detach_cleanup(task_t gTask, JNIEnv *env, jobject this_obj, bool thr
          Prelease(ph);
          return;
       }
    -JNF_COCOA_ENTER(env);
    +
    +  JNI_COCOA_ENTER(env);
     
       task_t gTask = getTask(env, this_obj);
       kern_return_t k_res = 0;
    @@ -1071,5 +1107,5 @@ static void detach_cleanup(task_t gTask, JNIEnv *env, jobject this_obj, bool thr
     
       detach_cleanup(gTask, env, this_obj, false);
     
    -JNF_COCOA_EXIT(env);
    +  JNI_COCOA_EXIT(env);
     }
    diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java
    index 4fe7a7f10a7..407ec298321 100644
    --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java
    +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java
    @@ -1157,7 +1157,7 @@ public void doit(Tokens t) {
                                     (System.getProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck") == null));
                     } else if (t.countTokens() == 1) {
                         if (Boolean.valueOf(t.nextToken()).booleanValue()) {
    -                        System.setProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck", null);
    +                        System.clearProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck");
                         } else {
                             System.setProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck", "true");
                         }
    diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciMethodData.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciMethodData.java
    index 873d7f4f7e6..2bad7f97a3e 100644
    --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciMethodData.java
    +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ci/ciMethodData.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -30,6 +30,7 @@
     import sun.jvm.hotspot.runtime.*;
     import sun.jvm.hotspot.oops.*;
     import sun.jvm.hotspot.types.*;
    +import sun.jvm.hotspot.types.Field;
     import sun.jvm.hotspot.utilities.Observable;
     import sun.jvm.hotspot.utilities.Observer;
     
    @@ -44,7 +45,7 @@ public void update(Observable o, Object data) {
     
       private static synchronized void initialize(TypeDataBase db) throws WrongTypeException {
         Type type      = db.lookupType("ciMethodData");
    -    origField = type.getAddressField("_orig");
    +    origField = type.getField("_orig");
         currentMileageField = new CIntField(type.getCIntegerField("_current_mileage"), 0);
         argReturnedField = new CIntField(type.getCIntegerField("_arg_returned"), 0);
         argStackField = new CIntField(type.getCIntegerField("_arg_stack"), 0);
    @@ -61,7 +62,7 @@ private static synchronized void initialize(TypeDataBase db) throws WrongTypeExc
         parametersTypeDataDi = new CIntField(typeMethodData.getCIntegerField("_parameters_type_data_di"), 0);
       }
     
    -  private static AddressField origField;
    +  private static Field origField;
       private static CIntField currentMileageField;
       private static CIntField argReturnedField;
       private static CIntField argStackField;
    @@ -106,8 +107,8 @@ private byte[] fetchDataAt(Address base, long size) {
       public byte[] orig() {
         // fetch the orig MethodData data between header and dataSize
         Address base = getAddress().addOffsetTo(origField.getOffset());
    -    byte[] result = new byte[MethodData.sizeofMethodDataOopDesc];
    -    for (int i = 0; i < MethodData.sizeofMethodDataOopDesc; i++) {
    +    byte[] result = new byte[(int)origField.getType().getSize()];
    +    for (int i = 0; i < result.length; i++) {
           result[i] = base.getJByteAt(i);
         }
         return result;
    @@ -116,7 +117,7 @@ public byte[] orig() {
       public  long[] data() {
         // Read the data as an array of intptr_t elements
         Address base = dataField.getValue(getAddress());
    -    int elements = dataSize() / MethodData.cellSize;
    +    int elements = (dataSize() + extraDataSize()) / MethodData.cellSize;
         long[] result = new long[elements];
         for (int i = 0; i < elements; i++) {
           Address value = base.getAddressAt(i * MethodData.cellSize);
    @@ -148,8 +149,7 @@ boolean outOfBounds(int dataIndex) {
       }
     
       ParametersTypeData parametersTypeData() {
    -    Address base = getAddress().addOffsetTo(origField.getOffset());
    -    int di = (int)parametersTypeDataDi.getValue(base);
    +    int di = (int)parametersTypeDataDi.getValue(getMetadata().getAddress());
         if (di == -1 || di == -2) {
           return null;
         }
    diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java
    index 1d67c993a38..491e3d5dc2c 100644
    --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java
    +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxCDebugger.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
      * Copyright (c) 2015, Red Hat Inc.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
    @@ -69,7 +69,6 @@ public LoadObject loadObjectContainingPC(Address pc) throws DebuggerException {
           LoadObject ob = (LoadObject) objs.get(i);
           Address base = ob.getBase();
           long size = ob.getSize();
    -      if (base == null) continue; // Skip. LoadObject was not properly initialized.
           if (pc.greaterThanOrEqual(base) && pc.lessThan(base.addOffsetTo(size))) {
             return ob;
           }
    diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/DataLayout.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/DataLayout.java
    index d55fdbc402c..3c3630cb0e6 100644
    --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/DataLayout.java
    +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/DataLayout.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -81,9 +81,8 @@ private int getU22(int at) {
         return data.getJShortAt(offset + at) & 0xffff;
       }
     
    -  int cellAt(int index) {
    -    // Cells are intptr_t sized but only contain ints as raw values
    -    return (int)data.getCIntegerAt(offset + cellOffset(index), MethodData.cellSize, false);
    +  long cellAt(int index) {
    +    return data.getCIntegerAt(offset + cellOffset(index), MethodData.cellSize, false);
       }
     
       public Address addressAt(int index) {
    diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Method.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Method.java
    index 8afb1f19767..a0c678b22f9 100644
    --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Method.java
    +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Method.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -267,7 +267,8 @@ public long getSize() {
       }
     
       public void printValueOn(PrintStream tty) {
    -    tty.print("Method " + getName().asString() + getSignature().asString() + "@" + getAddress());
    +      tty.print("Method " + getMethodHolder().getName().asString() + "." +
    +                getName().asString() + getSignature().asString() + "@" + getAddress());
       }
     
       public void iterateFields(MetadataVisitor visitor) {
    diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java
    index ea92fa56973..68d7808c196 100644
    --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java
    +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/MethodData.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -234,8 +234,8 @@ public void printValueOn(PrintStream tty) {
       public void iterateFields(MetadataVisitor visitor) {
         super.iterateFields(visitor);
         visitor.doMetadata(method, true);
    -      visitor.doCInt(size, true);
    -    }
    +    visitor.doCInt(size, true);
    +  }
     
       int dataSize() {
         if (dataSize == null) {
    diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ProfileData.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ProfileData.java
    index dce1b839d1c..29a127b6a49 100644
    --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ProfileData.java
    +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ProfileData.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -51,7 +51,7 @@ public int dp() {
       }
     
       // Low-level accessors for underlying data
    -  int intptrAt(int index) {
    +  long intptrAt(int index) {
         //assert(0 <= index && index < cellCount(), "oob");
         return data().cellAt(index);
       }
    diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/TypeEntries.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/TypeEntries.java
    index 8b791b5f938..16ba553a838 100644
    --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/TypeEntries.java
    +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/TypeEntries.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -48,17 +48,17 @@ public abstract class TypeEntries {
       final MethodDataInterface methodData;
     
       boolean wasNullSeen(int index) {
    -    int v = pd.intptrAt(index);
    +    long v = pd.intptrAt(index);
         return (v & nullSeen) != 0;
       }
     
       boolean isTypeUnknown(int index) {
    -    int v = pd.intptrAt(index);
    +    long v = pd.intptrAt(index);
         return (v & typeUnknown) != 0;
       }
     
       boolean isTypeNone(int index) {
    -    int v = pd.intptrAt(index);
    +    long v = pd.intptrAt(index);
         return (v & typeMask) == 0;
       }
     
    diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
    index aafd48a89b8..c830ac8d384 100644
    --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
    +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -467,7 +467,7 @@ private Frame cookLastFrame(Frame fr) {
         return fr;
       }
     
    -  private Address lastSPDbg() {
    +  public Address lastSPDbg() {
         return access.getLastSP(addr);
       }
     
    diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java
    index 498482305cd..d34d0f4e908 100644
    --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java
    +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -26,10 +26,13 @@
     
     import sun.jvm.hotspot.code.*;
     import sun.jvm.hotspot.debugger.*;
    +import sun.jvm.hotspot.debugger.cdbg.*;
     import sun.jvm.hotspot.gc.shared.*;
     import sun.jvm.hotspot.interpreter.*;
    -import sun.jvm.hotspot.runtime.*;
     import sun.jvm.hotspot.memory.*;
    +import sun.jvm.hotspot.oops.Metadata;
    +import sun.jvm.hotspot.runtime.*;
    +import sun.jvm.hotspot.types.WrongTypeException;
     
     /** This class, only intended for use in the debugging system,
         provides the functionality of find() in the VM. */
    @@ -37,7 +40,60 @@ provides the functionality of find() in the VM. */
     public class PointerFinder {
       public static PointerLocation find(Address a) {
         PointerLocation loc = new PointerLocation(a);
    +    Threads threads = VM.getVM().getThreads();
    +
    +    // Check if address is a pointer to a Metadata object.
    +    try {
    +      loc.metadata = Metadata.instantiateWrapperFor(a);
    +      return loc;
    +    } catch (Exception e) {
    +      // Just ignore. This just means we aren't dealing with a Metadata pointer.
    +    }
    +
    +    // Check if address is some other C++ type that we can deduce
    +    loc.ctype = VM.getVM().getTypeDataBase().guessTypeForAddress(a);
    +    if (loc.ctype == null && VM.getVM().isSharingEnabled()) {
    +      // Check if the value falls in the _md_region
    +      try {
    +        Address loc1 = a.getAddressAt(0);
    +        FileMapInfo cdsFileMapInfo = VM.getVM().getFileMapInfo();
    +        if (cdsFileMapInfo.inCopiedVtableSpace(loc1)) {
    +          loc.ctype = cdsFileMapInfo.getTypeForVptrAddress(loc1);
    +        }
    +      } catch (AddressException | WrongTypeException e) {
    +        // This can happen if "a" or "loc1" is a bad address. Just ignore.
    +      }
    +    }
    +    if (loc.ctype != null) {
    +      return loc;
    +    }
    +
    +    // Check if address is in the stack of a JavaThread
    +    for (int i = 0; i < threads.getNumberOfThreads(); i++) {
    +        JavaThread t = threads.getJavaThreadAt(i);
    +        Address stackBase = t.getStackBase();
    +        if (stackBase != null) {
    +            Long stackSize = t.getStackSize();
    +            Address stackEnd = stackBase.addOffsetTo(-stackSize);
    +            if (a.lessThanOrEqual(stackBase) && a.greaterThan(stackEnd)) {
    +                loc.stackThread = t;
    +                return loc;
    +            }
    +        }
    +    }
     
    +    // Check if address is a native (C++) symbol
    +    JVMDebugger dbg = VM.getVM().getDebugger();
    +    CDebugger cdbg = dbg.getCDebugger();
    +    if (cdbg != null) {
    +        loc.loadObject = cdbg.loadObjectContainingPC(a);
    +        if (loc.loadObject != null) {
    +            loc.nativeSymbol = loc.loadObject.closestSymbolToPC(a);
    +            return loc;
    +        }
    +    }
    +
    +    // Check if address is in the java heap.
         CollectedHeap heap = VM.getVM().getUniverse().heap();
         if (heap instanceof GenCollectedHeap) {
           GenCollectedHeap genheap = (GenCollectedHeap) heap;
    @@ -50,13 +106,12 @@ public static PointerLocation find(Address a) {
               }
             }
     
    -          if (Assert.ASSERTS_ENABLED) {
    +        if (Assert.ASSERTS_ENABLED) {
               Assert.that(loc.gen != null, "Should have found this in a generation");
             }
     
             if (VM.getVM().getUseTLAB()) {
               // Try to find thread containing it
    -          Threads threads = VM.getVM().getThreads();
               for (int i = 0; i < threads.getNumberOfThreads(); i++) {
                 JavaThread t = threads.getJavaThreadAt(i);
                 ThreadLocalAllocBuffer tlab = t.tlab();
    @@ -78,6 +133,7 @@ public static PointerLocation find(Address a) {
           }
         }
     
    +    // Check if address is in the interpreter
         Interpreter interp = VM.getVM().getInterpreter();
         if (interp.contains(a)) {
           loc.inInterpreter = true;
    @@ -85,6 +141,7 @@ public static PointerLocation find(Address a) {
           return loc;
         }
     
    +    // Check if address is in the code cache
         if (!VM.getVM().isCore()) {
           CodeCache c = VM.getVM().getCodeCache();
           if (c.contains(a)) {
    @@ -127,7 +184,6 @@ public static PointerLocation find(Address a) {
           return loc;
         }
         // Look in thread-local handles
    -    Threads threads = VM.getVM().getThreads();
         for (int i = 0; i < threads.getNumberOfThreads(); i++) {
           JavaThread t = threads.getJavaThreadAt(i);
           JNIHandleBlock handleBlock = t.activeHandles();
    diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java
    index 992a93885a8..aa2da619b46 100644
    --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java
    +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -27,10 +27,13 @@
     import java.io.*;
     import sun.jvm.hotspot.code.*;
     import sun.jvm.hotspot.debugger.*;
    +import sun.jvm.hotspot.debugger.cdbg.*;
     import sun.jvm.hotspot.gc.shared.*;
     import sun.jvm.hotspot.interpreter.*;
    -import sun.jvm.hotspot.runtime.*;
     import sun.jvm.hotspot.memory.*;
    +import sun.jvm.hotspot.oops.Metadata;
    +import sun.jvm.hotspot.runtime.*;
    +import sun.jvm.hotspot.types.Type;
     
     /** This class attempts to describe possible locations of pointers in
         the VM. */
    @@ -45,6 +48,13 @@ public class PointerLocation {
     
       Address addr;
     
    +  Metadata metadata;
    +  Type ctype;
    +  JavaThread stackThread;
    +
    +  LoadObject loadObject;
    +  ClosestSymbol nativeSymbol;
    +
       CollectedHeap heap;
       Generation gen;
     
    @@ -80,6 +90,22 @@ public PointerLocation(Address addr) {
         this.addr = addr;
       }
     
    +  public boolean isMetadata() {
    +    return metadata != null;
    +  }
    +
    +  public boolean isCtype() {
    +    return ctype != null;
    +  }
    +
    +  public boolean isInJavaStack() {
    +    return stackThread != null;
    +  }
    +
    +  public boolean isNativeSymbol() {
    +    return loadObject != null;
    +  }
    +
       public boolean isInHeap() {
         return (heap != null || (gen != null));
       }
    @@ -175,8 +201,9 @@ public sun.jvm.hotspot.runtime.Thread getJNIHandleThread() {
       }
     
       public boolean isUnknown() {
    -    return (!(isInHeap() || isInInterpreter() || isInCodeCache() ||
    -              isInStrongGlobalJNIHandles() || isInWeakGlobalJNIHandles() || isInLocalJNIHandleBlock()));
    +      return (!(isMetadata() || isCtype() || isInJavaStack() || isNativeSymbol() || isInHeap() ||
    +                isInInterpreter() || isInCodeCache() || isInStrongGlobalJNIHandles() ||
    +                isInWeakGlobalJNIHandles() || isInLocalJNIHandleBlock()));
       }
     
       public String toString() {
    @@ -186,24 +213,66 @@ public String toString() {
       }
     
       public void print() {
    -    printOn(System.out);
    +      printOn(System.out, true, true);
    +  }
    +
    +  public void print(boolean printAddress, boolean verbose) {
    +    printOn(System.out, printAddress, verbose);
       }
     
       public void printOn(PrintStream tty) {
    -    tty.print("Address ");
    -    if (addr == null) {
    -      tty.print("0x0");
    -    } else {
    -      tty.print(addr.toString());
    +    printOn(tty, true, true);
    +  }
    +
    +  public void printOn(PrintStream tty, boolean printAddress, boolean verbose) {
    +    if (printAddress) {
    +      tty.print("Address ");
    +      if (addr == null) {
    +        tty.print("0x0");
    +      } else {
    +        tty.print(addr.toString());
    +      }
    +      tty.print(": ");
         }
    -    tty.print(": ");
    -    if (isInHeap()) {
    +    if (isMetadata()) {
    +      metadata.printValueOn(tty); // does not include "\n"
    +      tty.println();
    +    } else if (isCtype()) {
    +      tty.println("Is of type " + ctype.getName());
    +    } else if (isInJavaStack()) {
    +        if (verbose) {
    +            tty.format("In java stack [%s,%s,%s] for thread %s:\n   ",
    +                       stackThread.getStackBase(), stackThread.lastSPDbg(),
    +                       stackThread.getStackBase().addOffsetTo(-stackThread.getStackSize()),
    +                       stackThread);
    +            stackThread.printThreadInfoOn(tty); // includes "\n"
    +        } else {
    +            tty.format("In java stack for thread \"%s\" %s\n", stackThread.getThreadName(), stackThread);
    +        }
    +    } else if (isNativeSymbol()) {
    +        CDebugger cdbg = VM.getVM().getDebugger().getCDebugger();
    +        long diff;
    +        if (nativeSymbol != null) {
    +            String name = nativeSymbol.getName();
    +            if (cdbg.canDemangle()) {
    +                name = cdbg.demangle(name);
    +            }
    +            tty.print(name);
    +            diff = nativeSymbol.getOffset();
    +        } else {
    +            tty.print(loadObject.getName());
    +            diff = addr.minus(loadObject.getBase());
    +        }
    +        if (diff != 0L) {
    +            tty.print(" + 0x" + Long.toHexString(diff));
    +        }
    +        tty.println();
    +    } else if (isInHeap()) {
           if (isInTLAB()) {
    -        tty.print("In thread-local allocation buffer for thread \"" +
    -                  getTLABThread().getThreadName() + "\" (");
    -        getTLABThread().printThreadIDOn(tty);
    +        tty.print("In thread-local allocation buffer for thread (");
    +        getTLABThread().printThreadInfoOn(tty);
             tty.print(") ");
    -        getTLAB().printOn(tty);
    +        getTLAB().printOn(tty); // includes "\n"
           } else {
             if (isInNewGen()) {
               tty.print("In new generation ");
    @@ -213,13 +282,16 @@ public void printOn(PrintStream tty) {
               tty.print("In unknown section of Java heap");
             }
             if (getGeneration() != null) {
    -          getGeneration().printOn(tty);
    +          getGeneration().printOn(tty); // does not include "\n"
             }
    +        tty.println();
           }
         } else if (isInInterpreter()) {
    -      tty.println("In interpreter codelet \"" + interpreterCodelet.getDescription() + "\"");
    -      interpreterCodelet.printOn(tty);
    +      tty.print("In interpreter codelet: ");
    +      interpreterCodelet.printOn(tty); // includes "\n"
         } else if (isInCodeCache()) {
    +      // TODO: print the type of CodeBlob. See "look for known code blobs" comment
    +      // in PStack.java for example code.
           CodeBlob b = getCodeBlob();
           tty.print("In ");
           if (isInBlobCode()) {
    @@ -235,28 +307,32 @@ public void printOn(PrintStream tty) {
             tty.print("unknown location");
           }
           tty.print(" in ");
    -      b.printOn(tty);
    +      if (verbose) {
    +          b.printOn(tty); // includes "\n"
    +      } else {
    +          tty.println(b.toString());
    +      }
     
           // FIXME: add more detail
         } else if (isInStrongGlobalJNIHandles()) {
    -      tty.print("In JNI strong global");
    +      tty.println("In JNI strong global");
         } else if (isInWeakGlobalJNIHandles()) {
    -      tty.print("In JNI weak global");
    +      tty.println("In JNI weak global");
         } else if (isInLocalJNIHandleBlock()) {
           tty.print("In thread-local");
           tty.print(" JNI handle block (" + handleBlock.top() + " handle slots present)");
           if (handleThread.isJavaThread()) {
             tty.print(" for JavaThread ");
    -        ((JavaThread) handleThread).printThreadIDOn(tty);
    +        ((JavaThread) handleThread).printThreadIDOn(tty); // includes "\n"
           } else {
    -        tty.print(" for a non-Java Thread");
    +        tty.println(" for a non-Java Thread");
           }
         } else {
           // This must be last
           if (Assert.ASSERTS_ENABLED) {
             Assert.that(isUnknown(), "Should have unknown location");
           }
    -      tty.print("In unknown location");
    +      tty.println("In unknown location");
         }
       }
     }
    diff --git a/src/jdk.hotspot.agent/share/man/jhsdb.1 b/src/jdk.hotspot.agent/share/man/jhsdb.1
    index c5891964668..8c6267c19ed 100644
    --- a/src/jdk.hotspot.agent/share/man/jhsdb.1
    +++ b/src/jdk.hotspot.agent/share/man/jhsdb.1
    @@ -21,7 +21,7 @@
     .\"
     .\" Automatically generated by Pandoc 2.3.1
     .\"
    -.TH "JHSDB" "1" "2020" "JDK 16" "JDK Commands"
    +.TH "JHSDB" "1" "2021" "JDK 17\-ea" "JDK Commands"
     .hy
     .SH NAME
     .PP
    diff --git a/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp b/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp
    index 52ce1f2d498..8d19c74916c 100644
    --- a/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp
    +++ b/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -503,6 +503,7 @@ static bool addLoadObjects(JNIEnv* env, jobject obj) {
         env->CallVoidMethod(obj, addLoadObject_ID, strName, (jlong) params[u].Size,
                             (jlong) params[u].Base);
         CHECK_EXCEPTION_(false);
    +    env->DeleteLocalRef(strName);
       }
     
       return true;
    @@ -629,6 +630,7 @@ static bool addThreads(JNIEnv* env, jobject obj) {
     
         env->CallVoidMethod(obj, setThreadIntegerRegisterSet_ID, (jlong)ptrThreadIds[t], regs);
         CHECK_EXCEPTION_(false);
    +    env->DeleteLocalRef(regs);
     
         ULONG sysId;
         COM_VERIFY_OK_(ptrIDebugSystemObjects->GetCurrentThreadSystemId(&sysId),
    diff --git a/src/jdk.jartool/share/man/jar.1 b/src/jdk.jartool/share/man/jar.1
    index b1861c59330..9bbc314f9df 100644
    --- a/src/jdk.jartool/share/man/jar.1
    +++ b/src/jdk.jartool/share/man/jar.1
    @@ -21,7 +21,7 @@
     .\"
     .\" Automatically generated by Pandoc 2.3.1
     .\"
    -.TH "JAR" "1" "2020" "JDK 16" "JDK Commands"
    +.TH "JAR" "1" "2021" "JDK 17\-ea" "JDK Commands"
     .hy
     .SH NAME
     .PP
    diff --git a/src/jdk.jartool/share/man/jarsigner.1 b/src/jdk.jartool/share/man/jarsigner.1
    index 74001244a9f..842a9a1fb92 100644
    --- a/src/jdk.jartool/share/man/jarsigner.1
    +++ b/src/jdk.jartool/share/man/jarsigner.1
    @@ -22,7 +22,7 @@
     .\"t
     .\" Automatically generated by Pandoc 2.3.1
     .\"
    -.TH "JARSIGNER" "1" "2020" "JDK 16" "JDK Commands"
    +.TH "JARSIGNER" "1" "2021" "JDK 17\-ea" "JDK Commands"
     .hy
     .SH NAME
     .PP
    @@ -960,15 +960,6 @@ incurs higher overhead.
     .RS
     .RE
     .TP
    -.B \f[CB]\-directsign\f[R]
    -By default, jarsigner stores the hash of the \f[CB]\&.SF\f[R] file and
    -possibly other information in a SignerInfo signedAttributes field, and
    -then calculates the signature on this field.
    -If this option is set, no SignerInfo signedAttributes field is generated
    -and the signature is calculated on the \f[CB]\&.SF\f[R] file directly.
    -.RS
    -.RE
    -.TP
     .B \f[CB]\-sectionsonly\f[R]
     If the \f[CB]\-sectionsonly\f[R] option appears on the command line, then
     the \f[CB]\&.SF\f[R] file (signature file) generated when a JAR file is
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java
    index 472f54955ba..b7d033557fb 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java
    @@ -32,11 +32,9 @@
     import javax.lang.model.element.ExecutableElement;
     import javax.lang.model.element.TypeElement;
     import javax.lang.model.element.VariableElement;
    -import javax.lang.model.type.ArrayType;
     import javax.lang.model.type.DeclaredType;
     import javax.lang.model.type.ExecutableType;
     import javax.lang.model.type.TypeMirror;
    -import javax.lang.model.type.TypeVariable;
     import javax.lang.model.util.SimpleTypeVisitor14;
     
     import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
    @@ -46,12 +44,12 @@
     import jdk.javadoc.internal.doclets.toolkit.Content;
     import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
     
    -import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.EXECUTABLE_MEMBER_PARAM;
    -import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.MEMBER;
    -import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.MEMBER_DEPRECATED_PREVIEW;
    -import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.MEMBER_TYPE_PARAMS;
    -import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.RECEIVER_TYPE;
    -import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.THROWS_TYPE;
    +import static jdk.javadoc.internal.doclets.formats.html.HtmlLinkInfo.Kind.EXECUTABLE_MEMBER_PARAM;
    +import static jdk.javadoc.internal.doclets.formats.html.HtmlLinkInfo.Kind.MEMBER;
    +import static jdk.javadoc.internal.doclets.formats.html.HtmlLinkInfo.Kind.MEMBER_DEPRECATED_PREVIEW;
    +import static jdk.javadoc.internal.doclets.formats.html.HtmlLinkInfo.Kind.MEMBER_TYPE_PARAMS;
    +import static jdk.javadoc.internal.doclets.formats.html.HtmlLinkInfo.Kind.RECEIVER_TYPE;
    +import static jdk.javadoc.internal.doclets.formats.html.HtmlLinkInfo.Kind.THROWS_TYPE;
     
     /**
      * Print method and constructor info.
    @@ -79,7 +77,7 @@ public AbstractExecutableMemberWriter(SubWriterHolderWriter writer) {
          * @return the type parameters.
          */
         protected Content getTypeParameters(ExecutableElement member) {
    -        LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, MEMBER_TYPE_PARAMS, member);
    +        HtmlLinkInfo linkInfo = new HtmlLinkInfo(configuration, MEMBER_TYPE_PARAMS, member);
             return writer.getTypeParameterLinks(linkInfo);
         }
     
    @@ -97,7 +95,8 @@ protected Content getSummaryLink(Element member) {
             }
             content.add(signature);
     
    -        return writer.getDocLink(MEMBER_DEPRECATED_PREVIEW, utils.getEnclosingTypeElement(member), member, content);
    +        return writer.getDocLink(MEMBER_DEPRECATED_PREVIEW, utils.getEnclosingTypeElement(member),
    +                member, content, null, false);
         }
     
         /**
    @@ -109,11 +108,10 @@ protected Content getSummaryLink(Element member) {
          * @param tdSummary the content tree to which the link will be added
          */
         @Override
    -    protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement te, Element member,
    -            Content tdSummary) {
    +    protected void addSummaryLink(HtmlLinkInfo.Kind context, TypeElement te, Element member,
    +                                  Content tdSummary) {
             ExecutableElement ee = (ExecutableElement)member;
    -        Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink,
    -                writer.getDocLink(context, te, ee, name(ee), false));
    +        Content memberLink = writer.getDocLink(context, te, ee, name(ee), HtmlStyle.memberNameLink);
             Content code = HtmlTree.CODE(memberLink);
             addParameters(ee, code);
             tdSummary.add(code);
    @@ -128,7 +126,7 @@ protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement te, Element
          */
         @Override
         protected void addInheritedSummaryLink(TypeElement te, Element member, Content linksTree) {
    -        linksTree.add(writer.getDocLink(MEMBER, te, member, name(member), false));
    +        linksTree.add(writer.getDocLink(MEMBER, te, member, name(member)));
         }
     
         /**
    @@ -141,7 +139,7 @@ protected void addInheritedSummaryLink(TypeElement te, Element member, Content l
          */
         protected void addParam(ExecutableElement member, VariableElement param, TypeMirror paramType,
                 boolean isVarArg, Content tree) {
    -        Content link = writer.getLink(new LinkInfoImpl(configuration, EXECUTABLE_MEMBER_PARAM,
    +        Content link = writer.getLink(new HtmlLinkInfo(configuration, EXECUTABLE_MEMBER_PARAM,
                     paramType).varargs(isVarArg));
             tree.add(link);
             if(name(param).length() > 0) {
    @@ -160,7 +158,7 @@ protected void addParam(ExecutableElement member, VariableElement param, TypeMir
          * @param tree the content tree to which the information will be added.
          */
         protected void addReceiver(ExecutableElement member, TypeMirror rcvrType, Content tree) {
    -        var info = new LinkInfoImpl(configuration, RECEIVER_TYPE, rcvrType);
    +        var info = new HtmlLinkInfo(configuration, RECEIVER_TYPE, rcvrType);
             info.linkToSelf = false;
             tree.add(writer.getLink(info));
             tree.add(Entity.NO_BREAK_SPACE);
    @@ -291,7 +289,7 @@ protected Content getExceptions(ExecutableElement member) {
                     htmlTree.add(",");
                     htmlTree.add(DocletConstants.NL);
                 }
    -            Content link = writer.getLink(new LinkInfoImpl(configuration, THROWS_TYPE, t));
    +            Content link = writer.getLink(new HtmlLinkInfo(configuration, THROWS_TYPE, t));
                 htmlTree.add(link);
             }
             return htmlTree;
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java
    index 144b8e42647..0cecb03c3b9 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java
    @@ -147,7 +147,7 @@ private Table getSummaryTable() {
          * @param tdSummary   the content tree to which the link will be added
          */
         protected void addSummaryLink(TypeElement typeElement, Element member, Content tdSummary) {
    -        addSummaryLink(LinkInfoImpl.Kind.MEMBER, typeElement, member, tdSummary);
    +        addSummaryLink(HtmlLinkInfo.Kind.MEMBER, typeElement, member, tdSummary);
         }
     
         /**
    @@ -158,8 +158,8 @@ protected void addSummaryLink(TypeElement typeElement, Element member, Content t
          * @param member      the member to be documented
          * @param tdSummary   the content tree to which the summary link will be added
          */
    -    protected abstract void addSummaryLink(LinkInfoImpl.Kind context,
    -            TypeElement typeElement, Element member, Content tdSummary);
    +    protected abstract void addSummaryLink(HtmlLinkInfo.Kind context,
    +                                           TypeElement typeElement, Element member, Content tdSummary);
     
         /**
          * Adds the inherited summary link for the member.
    @@ -210,8 +210,8 @@ protected void addModifierAndType(Element member, TypeMirror type,
                     }
                 }
                 code.add(
    -                    writer.getLink(new LinkInfoImpl(configuration,
    -                            LinkInfoImpl.Kind.SUMMARY_RETURN_TYPE, type)));
    +                    writer.getLink(new HtmlLinkInfo(configuration,
    +                            HtmlLinkInfo.Kind.SUMMARY_RETURN_TYPE, type)));
             }
             tdSummaryType.add(code);
         }
    @@ -336,8 +336,8 @@ protected void addUseInfo(List members, Content heading, Cont
                     typeContent.add(name);
                 }
                 addSummaryLink(utils.isClass(element) || utils.isInterface(element)
    -                    ? LinkInfoImpl.Kind.CLASS_USE
    -                    : LinkInfoImpl.Kind.MEMBER,
    +                    ? HtmlLinkInfo.Kind.CLASS_USE
    +                    : HtmlLinkInfo.Kind.MEMBER,
                         te, element, typeContent);
                 Content desc = new ContentBuilder();
                 writer.addSummaryLinkComment(this, element, desc);
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java
    index 0b7ecf21c1d..96ee6251a4e 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractTreeWriter.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -154,7 +154,7 @@ protected void addExtendsImplements(TypeElement parent,
                             } else {
                                 contentTree.add(", ");
                             }
    -                        addPreQualifiedClassLink(LinkInfoImpl.Kind.TREE, intf, contentTree);
    +                        addPreQualifiedClassLink(HtmlLinkInfo.Kind.TREE, intf, contentTree);
                         }
                     }
                 }
    @@ -171,6 +171,6 @@ protected void addExtendsImplements(TypeElement parent,
          * @param contentTree the content tree to which the information will be added
          */
         protected void addPartialInfo(TypeElement typeElement, Content contentTree) {
    -        addPreQualifiedStrongClassLink(LinkInfoImpl.Kind.TREE, typeElement, contentTree);
    +        addPreQualifiedStrongClassLink(HtmlLinkInfo.Kind.TREE, typeElement, contentTree);
         }
     }
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java
    index 83c79884103..1d021608fc8 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AllClassesIndexWriter.java
    @@ -151,8 +151,8 @@ protected void addContents(Content content) {
          */
         protected void addTableRow(Table table, TypeElement klass) {
             List rowContents = new ArrayList<>();
    -        Content classLink = getLink(new LinkInfoImpl(
    -                configuration, LinkInfoImpl.Kind.INDEX, klass));
    +        Content classLink = getLink(new HtmlLinkInfo(
    +                configuration, HtmlLinkInfo.Kind.INDEX, klass));
             ContentBuilder description = new ContentBuilder();
             Set flags = utils.elementFlags(klass);
             if (flags.contains(ElementFlag.PREVIEW)) {
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java
    index 7f19b0a50bd..bb08a645389 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java
    @@ -184,10 +184,10 @@ public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedT
         }
     
         @Override
    -    protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element member,
    -            Content tdSummary) {
    -        Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink,
    -                writer.getDocLink(context, member, name(member), false));
    +    protected void addSummaryLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Element member,
    +                                  Content tdSummary) {
    +        Content memberLink = writer.getDocLink(context, utils.getEnclosingTypeElement(member), member,
    +                name(member), HtmlStyle.memberNameLink);
             Content code = HtmlTree.CODE(memberLink);
             tdSummary.add(code);
         }
    @@ -206,7 +206,7 @@ protected void addSummaryType(Element member, Content tdSummaryType) {
         @Override
         protected Content getSummaryLink(Element member) {
             String name = utils.getFullyQualifiedName(member) + "." + member.getSimpleName();
    -        return writer.getDocLink(LinkInfoImpl.Kind.MEMBER_DEPRECATED_PREVIEW, member, name);
    +        return writer.getDocLink(HtmlLinkInfo.Kind.MEMBER_DEPRECATED_PREVIEW, member, name);
         }
     
         protected Comment selectComment(Comment c1, Comment c2) {
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java
    index 1f02961b59e..cd48a91e026 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassUseWriter.java
    @@ -252,8 +252,8 @@ protected void addClassUse(Content contentTree) {
         protected void addPackageList(Content contentTree) {
             Content caption = contents.getContent(
                     "doclet.ClassUse_Packages.that.use.0",
    -                getLink(new LinkInfoImpl(configuration,
    -                        LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement)));
    +                getLink(new HtmlLinkInfo(configuration,
    +                        HtmlLinkInfo.Kind.CLASS_USE_HEADER, typeElement)));
             Table table = new Table(HtmlStyle.summaryTable)
                     .setCaption(caption)
                     .setHeader(getPackageTableHeader())
    @@ -277,8 +277,8 @@ protected void addPackageAnnotationList(Content contentTree) {
             }
             Content caption = contents.getContent(
                     "doclet.ClassUse_PackageAnnotation",
    -                getLink(new LinkInfoImpl(configuration,
    -                        LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement)));
    +                getLink(new HtmlLinkInfo(configuration,
    +                        HtmlLinkInfo.Kind.CLASS_USE_HEADER, typeElement)));
     
             Table table = new Table(HtmlStyle.summaryTable)
                     .setCaption(caption)
    @@ -304,7 +304,7 @@ protected void addClassList(Content contentTree) {
                 HtmlTree htmlTree = HtmlTree.SECTION(HtmlStyle.detail)
                         .setId(htmlIds.forPackage(pkg));
                 Content link = contents.getContent("doclet.ClassUse_Uses.of.0.in.1",
    -                    getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.CLASS_USE_HEADER,
    +                    getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.CLASS_USE_HEADER,
                                 typeElement)),
                         getPackageLink(pkg, utils.getPackageName(pkg)));
                 Content heading = HtmlTree.HEADING(Headings.TypeUse.SUMMARY_HEADING, link);
    @@ -337,8 +337,8 @@ protected void addPackageUse(PackageElement pkg, Table table) {
          * @param contentTree the content tree to which the class use information will be added
          */
         protected void addClassUse(PackageElement pkg, Content contentTree) {
    -        Content classLink = getLink(new LinkInfoImpl(configuration,
    -            LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement));
    +        Content classLink = getLink(new HtmlLinkInfo(configuration,
    +            HtmlLinkInfo.Kind.CLASS_USE_HEADER, typeElement));
             Content pkgLink = getPackageLink(pkg, utils.getPackageName(pkg));
             classSubWriter.addUseInfo(pkgToClassAnnotations.get(pkg),
                     contents.getContent("doclet.ClassUse_Annotation", classLink,
    @@ -437,8 +437,8 @@ protected HtmlTree getClassUseHeader() {
         protected Navigation getNavBar(PageMode pageMode, Element element) {
             Content mdleLinkContent = getModuleLink(utils.elementUtils.getModuleOf(typeElement),
                     contents.moduleLabel);
    -        Content classLinkContent = getLink(new LinkInfoImpl(
    -                configuration, LinkInfoImpl.Kind.CLASS_USE_HEADER, typeElement)
    +        Content classLinkContent = getLink(new HtmlLinkInfo(
    +                configuration, HtmlLinkInfo.Kind.CLASS_USE_HEADER, typeElement)
                     .label(resources.getText("doclet.Class"))
                     .skipPreview(true));
             return super.getNavBar(pageMode, element)
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
    index 7d99e7f149f..28f78c7ccc9 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java
    @@ -127,8 +127,8 @@ public Content getHeader(String header) {
                 pkgNameDiv.add(pkgNameContent);
                 div.add(pkgNameDiv);
             }
    -        LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
    -                LinkInfoImpl.Kind.CLASS_HEADER, typeElement);
    +        HtmlLinkInfo linkInfo = new HtmlLinkInfo(configuration,
    +                HtmlLinkInfo.Kind.CLASS_HEADER, typeElement);
             //Let's not link to ourselves in the header.
             linkInfo.linkToSelf = false;
             Content heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING,
    @@ -267,7 +267,7 @@ private Content getTreeForClassHelper(TypeMirror type) {
             Content content = new ContentBuilder();
             if (type.equals(typeElement.asType())) {
                 Content typeParameters = getTypeParameterLinks(
    -                    new LinkInfoImpl(configuration, LinkInfoImpl.Kind.TREE,
    +                    new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.TREE,
                         typeElement));
                 if (configuration.shouldExcludeQualifier(utils.containingPackage(typeElement).toString())) {
                     content.add(utils.asTypeElement(type).getSimpleName());
    @@ -277,8 +277,8 @@ private Content getTreeForClassHelper(TypeMirror type) {
                     content.add(typeParameters);
                 }
             } else {
    -            Content link = getLink(new LinkInfoImpl(configuration,
    -                    LinkInfoImpl.Kind.CLASS_TREE_PARENT, type)
    +            Content link = getLink(new HtmlLinkInfo(configuration,
    +                    HtmlLinkInfo.Kind.CLASS_TREE_PARENT, type)
                         .label(configuration.getClassName(utils.asTypeElement(type))));
                 content.add(link);
             }
    @@ -316,7 +316,7 @@ public void addSubClassInfo(Content classInfoTree) {
                 if (!subclasses.isEmpty()) {
                     HtmlTree dl = HtmlTree.DL(HtmlStyle.notes);
                     dl.add(HtmlTree.DT(contents.subclassesLabel));
    -                dl.add(HtmlTree.DD(getClassLinks(LinkInfoImpl.Kind.SUBCLASSES, subclasses)));
    +                dl.add(HtmlTree.DD(getClassLinks(HtmlLinkInfo.Kind.SUBCLASSES, subclasses)));
                     classInfoTree.add(dl);
                 }
             }
    @@ -329,7 +329,7 @@ public void addSubInterfacesInfo(Content classInfoTree) {
                 if (!subInterfaces.isEmpty()) {
                     Content dl = HtmlTree.DL(HtmlStyle.notes);
                     dl.add(HtmlTree.DT(contents.subinterfacesLabel));
    -                dl.add(HtmlTree.DD(getClassLinks(LinkInfoImpl.Kind.SUBINTERFACES, subInterfaces)));
    +                dl.add(HtmlTree.DD(getClassLinks(HtmlLinkInfo.Kind.SUBINTERFACES, subInterfaces)));
                     classInfoTree.add(dl);
                 }
             }
    @@ -349,7 +349,7 @@ public void addInterfaceUsageInfo (Content classInfoTree) {
             if (!implcl.isEmpty()) {
                 HtmlTree dl = HtmlTree.DL(HtmlStyle.notes);
                 dl.add(HtmlTree.DT(contents.implementingClassesLabel));
    -            dl.add(HtmlTree.DD(getClassLinks(LinkInfoImpl.Kind.IMPLEMENTED_CLASSES, implcl)));
    +            dl.add(HtmlTree.DD(getClassLinks(HtmlLinkInfo.Kind.IMPLEMENTED_CLASSES, implcl)));
                 classInfoTree.add(dl);
             }
         }
    @@ -361,7 +361,7 @@ public void addImplementedInterfacesInfo(Content classInfoTree) {
             if (utils.isClass(typeElement) && !interfaces.isEmpty()) {
                 HtmlTree dl = HtmlTree.DL(HtmlStyle.notes);
                 dl.add(HtmlTree.DT(contents.allImplementedInterfacesLabel));
    -            dl.add(HtmlTree.DD(getClassLinks(LinkInfoImpl.Kind.IMPLEMENTED_INTERFACES, interfaces)));
    +            dl.add(HtmlTree.DD(getClassLinks(HtmlLinkInfo.Kind.IMPLEMENTED_INTERFACES, interfaces)));
                 classInfoTree.add(dl);
             }
         }
    @@ -375,7 +375,7 @@ public void addSuperInterfacesInfo(Content classInfoTree) {
             if (utils.isInterface(typeElement) && !interfaces.isEmpty()) {
                 HtmlTree dl = HtmlTree.DL(HtmlStyle.notes);
                 dl.add(HtmlTree.DT(contents.allSuperinterfacesLabel));
    -            dl.add(HtmlTree.DD(getClassLinks(LinkInfoImpl.Kind.SUPER_INTERFACES, interfaces)));
    +            dl.add(HtmlTree.DD(getClassLinks(HtmlLinkInfo.Kind.SUPER_INTERFACES, interfaces)));
                 classInfoTree.add(dl);
             }
         }
    @@ -393,8 +393,8 @@ public Void visitType(TypeElement e, Void p) {
                             ? contents.enclosingInterfaceLabel
                             : contents.enclosingClassLabel));
                     Content dd = new HtmlTree(TagName.DD);
    -                dd.add(getLink(new LinkInfoImpl(configuration,
    -                        LinkInfoImpl.Kind.CLASS, e)));
    +                dd.add(getLink(new HtmlLinkInfo(configuration,
    +                        HtmlLinkInfo.Kind.CLASS, e)));
                     dl.add(dd);
                     classInfoTree.add(dl);
                     return null;
    @@ -450,7 +450,7 @@ public void addClassDeprecationInfo(Content classInfoTree) {
          * @param list the list of classes
          * @return a content tree for the class list
          */
    -    private Content getClassLinks(LinkInfoImpl.Kind context, Collection list) {
    +    private Content getClassLinks(HtmlLinkInfo.Kind context, Collection list) {
             Content content = new ContentBuilder();
             boolean isFirst = true;
             for (Object type : list) {
    @@ -463,11 +463,11 @@ private Content getClassLinks(LinkInfoImpl.Kind context, Collection list) {
                 // TODO: should we simply split this method up to avoid instanceof ?
                 if (type instanceof TypeElement) {
                     Content link = getLink(
    -                        new LinkInfoImpl(configuration, context, (TypeElement)(type)));
    +                        new HtmlLinkInfo(configuration, context, (TypeElement)(type)));
                     content.add(HtmlTree.CODE(link));
                 } else {
                     Content link = getLink(
    -                        new LinkInfoImpl(configuration, context, ((TypeMirror)type)));
    +                        new HtmlLinkInfo(configuration, context, ((TypeMirror)type)));
                     content.add(HtmlTree.CODE(link));
                 }
             }
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java
    index 43128f419d9..367c738c4d7 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -184,8 +184,8 @@ public void addConstantMembers(TypeElement typeElement, Collection classes) {
             return null;
         }
     
    -    protected boolean checkForDeprecation(DocletEnvironment docEnv) {
    +    protected boolean checkForDeprecation() {
             for (TypeElement te : getIncludedTypeElements()) {
                 if (isGeneratedDoc(te)) {
                     return true;
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
    index 85d4739b87a..22bb75df807 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java
    @@ -313,7 +313,7 @@ private void addMethodInfo(ExecutableElement method, Content dl) {
             // printed. If no overridden or implementation info needs to be
             // printed, do not print this section.
             if ((!intfacs.isEmpty()
    -                && vmt.getImplementedMethods(method).isEmpty() == false)
    +                && !vmt.getImplementedMethods(method).isEmpty())
                     || overriddenMethod != null) {
                 MethodWriterImpl.addImplementsInfo(this, method, dl);
                 if (overriddenMethod != null) {
    @@ -750,8 +750,8 @@ public void addSrcLink(Element element, Content label, Content htmltree) {
          *
          * @return the link for the given class.
          */
    -    public Content getLink(LinkInfoImpl linkInfo) {
    -        LinkFactoryImpl factory = new LinkFactoryImpl(this);
    +    public Content getLink(HtmlLinkInfo linkInfo) {
    +        HtmlLinkFactory factory = new HtmlLinkFactory(this);
             return factory.getLink(linkInfo);
         }
     
    @@ -761,9 +761,9 @@ public Content getLink(LinkInfoImpl linkInfo) {
          * @param linkInfo the information about the link.
          * @return the type for the given class.
          */
    -    public Content getTypeParameterLinks(LinkInfoImpl linkInfo) {
    -        LinkFactoryImpl factory = new LinkFactoryImpl(this);
    -        return factory.getTypeParameterLinks(linkInfo, false);
    +    public Content getTypeParameterLinks(HtmlLinkInfo linkInfo) {
    +        HtmlLinkFactory factory = new HtmlLinkFactory(this);
    +        return factory.getTypeParameterLinks(linkInfo);
         }
     
         /*************************************************************
    @@ -775,12 +775,12 @@ public Content getTypeParameterLinks(LinkInfoImpl linkInfo) {
          * @param refMemName the name of the member being referenced.  This should
          * be null or empty string if no member is being referenced.
          * @param label the label for the external link.
    -     * @param strong true if the link should be strong.
    +     * @param style optional style for the link.
          * @param code true if the label should be code font.
          * @return the link
          */
         public Content getCrossClassLink(TypeElement classElement, String refMemName,
    -                                    Content label, boolean strong, boolean code) {
    +                                    Content label, HtmlStyle style, boolean code) {
             if (classElement != null) {
                 String className = utils.getSimpleName(classElement);
                 PackageElement packageElement = utils.containingPackage(classElement);
    @@ -798,8 +798,7 @@ class (assuming that it exists).  This is definitely a limitation of
                     DocLink link = configuration.extern.getExternalLink(packageElement, pathToRoot,
                                     className + ".html", refMemName);
                     return links.createLink(link,
    -                    (label == null) || label.isEmpty() ? defaultLabel : label,
    -                    strong,
    +                    (label == null) || label.isEmpty() ? defaultLabel : label, style,
                         resources.getText("doclet.Href_Class_Or_Interface_Title",
                             utils.getPackageName(packageElement)), true);
                 }
    @@ -807,13 +806,6 @@ class (assuming that it exists).  This is definitely a limitation of
             return null;
         }
     
    -    public boolean isClassLinkable(TypeElement typeElement) {
    -        if (utils.isIncluded(typeElement)) {
    -            return configuration.isGeneratedDoc(typeElement);
    -        }
    -        return configuration.extern.isExternal(typeElement);
    -    }
    -
         public DocLink getCrossPackageLink(PackageElement element) {
             return configuration.extern.getExternalLink(element, pathToRoot,
                 DocPaths.PACKAGE_SUMMARY.getPath());
    @@ -831,9 +823,9 @@ public DocLink getCrossModuleLink(ModuleElement element) {
          * @param element to link to
          * @return a content tree for the link
          */
    -    public Content getQualifiedClassLink(LinkInfoImpl.Kind context, Element element) {
    -        LinkInfoImpl linkInfoImpl = new LinkInfoImpl(configuration, context, (TypeElement)element);
    -        return getLink(linkInfoImpl.label(utils.getFullyQualifiedName(element)));
    +    public Content getQualifiedClassLink(HtmlLinkInfo.Kind context, Element element) {
    +        HtmlLinkInfo htmlLinkInfo = new HtmlLinkInfo(configuration, context, (TypeElement)element);
    +        return getLink(htmlLinkInfo.label(utils.getFullyQualifiedName(element)));
         }
     
         /**
    @@ -843,8 +835,8 @@ public Content getQualifiedClassLink(LinkInfoImpl.Kind context, Element element)
          * @param typeElement to link to
          * @param contentTree the content tree to which the link will be added
          */
    -    public void addPreQualifiedClassLink(LinkInfoImpl.Kind context, TypeElement typeElement, Content contentTree) {
    -        addPreQualifiedClassLink(context, typeElement, false, contentTree);
    +    public void addPreQualifiedClassLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Content contentTree) {
    +        addPreQualifiedClassLink(context, typeElement, null, contentTree);
         }
     
         /**
    @@ -853,18 +845,16 @@ public void addPreQualifiedClassLink(LinkInfoImpl.Kind context, TypeElement type
          * link label.
          *
          * @param typeElement the class to link to.
    -     * @param isStrong true if the link should be strong.
          * @return the link with the package portion of the label in plain text.
          */
    -    public Content getPreQualifiedClassLink(LinkInfoImpl.Kind context,
    -            TypeElement typeElement, boolean isStrong) {
    +    public Content getPreQualifiedClassLink(HtmlLinkInfo.Kind context, TypeElement typeElement) {
             ContentBuilder classlink = new ContentBuilder();
             PackageElement pkg = utils.containingPackage(typeElement);
             if (pkg != null && ! configuration.shouldExcludeQualifier(pkg.getSimpleName().toString())) {
                 classlink.add(getEnclosingPackageName(typeElement));
             }
    -        classlink.add(getLink(new LinkInfoImpl(configuration,
    -                context, typeElement).label(utils.getSimpleName(typeElement)).strong(isStrong)));
    +        classlink.add(getLink(new HtmlLinkInfo(configuration,
    +                context, typeElement).label(utils.getSimpleName(typeElement))));
             return classlink;
         }
     
    @@ -875,18 +865,18 @@ public Content getPreQualifiedClassLink(LinkInfoImpl.Kind context,
          *
          * @param context the id of the context where the link will be added
          * @param typeElement the class to link to
    -     * @param isStrong true if the link should be strong
    +     * @param style optional style for the link
          * @param contentTree the content tree to which the link with be added
          */
    -    public void addPreQualifiedClassLink(LinkInfoImpl.Kind context,
    -            TypeElement typeElement, boolean isStrong, Content contentTree) {
    +    public void addPreQualifiedClassLink(HtmlLinkInfo.Kind context,
    +                                         TypeElement typeElement, HtmlStyle style, Content contentTree) {
             PackageElement pkg = utils.containingPackage(typeElement);
             if(pkg != null && ! configuration.shouldExcludeQualifier(pkg.getSimpleName().toString())) {
                 contentTree.add(getEnclosingPackageName(typeElement));
             }
    -        LinkInfoImpl linkinfo = new LinkInfoImpl(configuration, context, typeElement)
    +        HtmlLinkInfo linkinfo = new HtmlLinkInfo(configuration, context, typeElement)
                     .label(utils.getSimpleName(typeElement))
    -                .strong(isStrong);
    +                .style(style);
             Content link = getLink(linkinfo);
             contentTree.add(link);
         }
    @@ -920,8 +910,8 @@ protected TypeElement getCurrentPageElement() {
          * @param typeElement the class to link to
          * @param contentTree the content tree to which the link with be added
          */
    -    public void addPreQualifiedStrongClassLink(LinkInfoImpl.Kind context, TypeElement typeElement, Content contentTree) {
    -        addPreQualifiedClassLink(context, typeElement, true, contentTree);
    +    public void addPreQualifiedStrongClassLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Content contentTree) {
    +        addPreQualifiedClassLink(context, typeElement, HtmlStyle.typeNameLink, contentTree);
         }
     
         /**
    @@ -932,67 +922,75 @@ public void addPreQualifiedStrongClassLink(LinkInfoImpl.Kind context, TypeElemen
          * @param label the label for the link
          * @return a content tree for the element link
          */
    -    public Content getDocLink(LinkInfoImpl.Kind context, Element element, CharSequence label) {
    +    public Content getDocLink(HtmlLinkInfo.Kind context, Element element, CharSequence label) {
             return getDocLink(context, utils.getEnclosingTypeElement(element), element,
    -                new StringContent(label));
    +                new StringContent(label), null, false);
         }
     
         /**
          * Return the link for the given member.
          *
          * @param context the id of the context where the link will be printed.
    +     * @param typeElement the typeElement that we should link to. This is not
    +     *            not necessarily the type containing element since we may be
    +     *            inheriting comments.
          * @param element the member being linked to.
          * @param label the label for the link.
    -     * @param strong true if the link should be strong.
          * @return the link for the given member.
          */
    -    public Content getDocLink(LinkInfoImpl.Kind context, Element element, CharSequence label,
    -            boolean strong) {
    -        return getDocLink(context, utils.getEnclosingTypeElement(element), element, label, strong);
    +    public Content getDocLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Element element,
    +                              CharSequence label) {
    +        return getDocLink(context, typeElement, element, new StringContent(label), null, false);
         }
     
         /**
          * Return the link for the given member.
          *
          * @param context the id of the context where the link will be printed.
    -     * @param typeElement the typeElement that we should link to.  This is not
    -                 necessarily equal to element.containingClass().  We may be
    -                 inheriting comments.
    +     * @param typeElement the typeElement that we should link to. This is not
    +     *            not necessarily the type containing element since we may be
    +     *            inheriting comments.
          * @param element the member being linked to.
          * @param label the label for the link.
    -     * @param strong true if the link should be strong.
    +     * @param style optional style for the link.
          * @return the link for the given member.
          */
    -    public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
    -            CharSequence label, boolean strong) {
    -        return getDocLink(context, typeElement, element, label, strong, false);
    +    public Content getDocLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Element element,
    +                              CharSequence label, HtmlStyle style) {
    +        return getDocLink(context, typeElement, element, new StringContent(label), style, false);
         }
     
    -    public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
    -            Content label, boolean strong) {
    -        return getDocLink(context, typeElement, element, label, strong, false);
    +    /**
    +     * Return the link for the given member.
    +     *
    +     * @param context the id of the context where the link will be printed.
    +     * @param typeElement the typeElement that we should link to. This is not
    +     *            not necessarily the type containing element since we may be
    +     *            inheriting comments.
    +     * @param element the member being linked to.
    +     * @param label the label for the link.
    +     * @return the link for the given member.
    +     */
    +    public Content getDocLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Element element,
    +                              CharSequence label, boolean isProperty) {
    +        return getDocLink(context, typeElement, element, new StringContent(label), null, isProperty);
         }
     
         /**
          * Return the link for the given member.
          *
          * @param context the id of the context where the link will be printed.
    -     * @param typeElement the typeElement that we should link to.  This is not
    -                 necessarily equal to element.containingClass().  We may be
    -                 inheriting comments.
    +     * @param typeElement the typeElement that we should link to. This is not
    +     *            not necessarily the type containing element since we may be
    +     *            inheriting comments.
          * @param element the member being linked to.
          * @param label the label for the link.
    -     * @param strong true if the link should be strong.
    +     * @param style optional style to use for the link.
          * @param isProperty true if the element parameter is a JavaFX property.
          * @return the link for the given member.
          */
    -    public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
    -            CharSequence label, boolean strong, boolean isProperty) {
    -        return getDocLink(context, typeElement, element, new StringContent(label), strong, isProperty);
    -    }
    -
    -    public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
    -            Content label, boolean strong, boolean isProperty) {
    +    public Content getDocLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Element element,
    +                              Content label, HtmlStyle style, boolean isProperty) {
             if (!utils.isLinkable(typeElement, element)) {
                 return label;
             }
    @@ -1000,55 +998,24 @@ public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, El
             if (utils.isExecutableElement(element)) {
                 ExecutableElement ee = (ExecutableElement)element;
                 HtmlId id = isProperty ? htmlIds.forProperty(ee) : htmlIds.forMember(ee);
    -            return getLink(new LinkInfoImpl(configuration, context, typeElement)
    +            return getLink(new HtmlLinkInfo(configuration, context, typeElement)
                     .label(label)
                     .where(id.name())
    -                .targetMember(element)
    -                .strong(strong));
    +                .style(style)
    +                .targetMember(element));
             }
     
             if (utils.isVariableElement(element) || utils.isTypeElement(element)) {
    -            return getLink(new LinkInfoImpl(configuration, context, typeElement)
    +            return getLink(new HtmlLinkInfo(configuration, context, typeElement)
                     .label(label)
                     .where(element.getSimpleName().toString())
    -                .targetMember(element)
    -                .strong(strong));
    +                .style(style)
    +                .targetMember(element));
             }
     
             return label;
         }
     
    -    /**
    -     * Return the link for the given member.
    -     *
    -     * @param context the id of the context where the link will be added
    -     * @param typeElement the typeElement that we should link to.  This is not
    -                 necessarily equal to element.containingClass().  We may be
    -                 inheriting comments
    -     * @param element the member being linked to
    -     * @param label the label for the link
    -     * @return the link for the given member
    -     */
    -    public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element,
    -            Content label) {
    -        if (!(utils.isIncluded(element) || utils.isLinkable(typeElement))) {
    -            return label;
    -        } else if (utils.isExecutableElement(element)) {
    -            ExecutableElement emd = (ExecutableElement) element;
    -            return getLink(new LinkInfoImpl(configuration, context, typeElement)
    -                    .label(label)
    -                    .where(htmlIds.forMember(emd).name())
    -                    .targetMember(element));
    -        } else if (utils.isVariableElement(element) || utils.isTypeElement(element)) {
    -            return getLink(new LinkInfoImpl(configuration, context, typeElement)
    -                    .label(label)
    -                    .where(element.getSimpleName().toString())
    -                    .targetMember(element));
    -        } else {
    -            return label;
    -        }
    -    }
    -
         public Content seeTagToContent(Element element, DocTree see) {
             Kind kind = see.getKind();
             if (!(kind == LINK || kind == SEE || kind == LINK_PLAIN)) {
    @@ -1116,12 +1083,12 @@ public Content seeTagToContent(Element element, DocTree see) {
                         TypeMirror refType = ch.getReferencedType(see);
                         if (refType != null) {
                             return plainOrCode(isLinkPlain, getLink(
    -                                new LinkInfoImpl(configuration, LinkInfoImpl.Kind.DEFAULT, refType)));
    +                                new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.DEFAULT, refType)));
                         }
                     }
                     label = plainOrCode(isLinkPlain, new StringContent(utils.getSimpleName(refClass)));
                 }
    -            return getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.DEFAULT, refClass)
    +            return getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.DEFAULT, refClass)
                         .label(label));
             } else if (refMem == null) {
                 // Must be a member reference since refClass is not null and refMemName is not null.
    @@ -1177,8 +1144,8 @@ public Content seeTagToContent(Element element, DocTree see) {
     
                 text = plainOrCode(kind == LINK_PLAIN, new StringContent(refMemName));
     
    -            return getDocLink(LinkInfoImpl.Kind.SEE_TAG, containing,
    -                    refMem, (label.isEmpty() ? text: label), false);
    +            return getDocLink(HtmlLinkInfo.Kind.SEE_TAG, containing,
    +                    refMem, (label.isEmpty() ? text: label), null, false);
             }
         }
     
    @@ -1797,8 +1764,8 @@ public List getAnnotations(List descList, b
                 }
                 annotation = new ContentBuilder();
                 isAnnotationDocumented = false;
    -            LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
    -                                                     LinkInfoImpl.Kind.ANNOTATION, annotationElement);
    +            HtmlLinkInfo linkInfo = new HtmlLinkInfo(configuration,
    +                                                     HtmlLinkInfo.Kind.ANNOTATION, annotationElement);
                 Map pairs = aDesc.getElementValues();
                 // If the annotation is synthesized, do not print the container.
                 if (utils.configuration.workArounds.isSynthesized(aDesc)) {
    @@ -1873,7 +1840,7 @@ public Void visitArray(List vals, List map,
                                     boolean linkBreak) {
    @@ -1900,8 +1867,7 @@ private void addAnnotations(TypeElement annotationDoc, LinkInfoImpl linkInfo,
                     }
                     String simpleName = element.getSimpleName().toString();
                     if (multipleValues || !"value".equals(simpleName)) { // Omit "value=" where unnecessary
    -                    annotation.add(getDocLink(LinkInfoImpl.Kind.ANNOTATION,
    -                                                     element, simpleName, false));
    +                    annotation.add(getDocLink(HtmlLinkInfo.Kind.ANNOTATION, element, simpleName));
                         annotation.add("=");
                     }
                     AnnotationValue annotationValue = map.get(element);
    @@ -1990,8 +1956,8 @@ public Content visitType(TypeMirror t, Void p) {
                     return new SimpleTypeVisitor9() {
                         @Override
                         public Content visitDeclared(DeclaredType t, Void p) {
    -                        LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
    -                                LinkInfoImpl.Kind.ANNOTATION, t);
    +                        HtmlLinkInfo linkInfo = new HtmlLinkInfo(configuration,
    +                                HtmlLinkInfo.Kind.ANNOTATION, t);
                             String name = utils.isIncluded(t.asElement())
                                     ? t.asElement().getSimpleName().toString()
                                     : utils.getFullyQualifiedName(t.asElement());
    @@ -2015,8 +1981,7 @@ public Content visitAnnotation(AnnotationMirror a, Void p) {
                 }
                 @Override
                 public Content visitEnumConstant(VariableElement c, Void p) {
    -                return getDocLink(LinkInfoImpl.Kind.ANNOTATION,
    -                        c, c.getSimpleName(), false);
    +                return getDocLink(HtmlLinkInfo.Kind.ANNOTATION, c, c.getSimpleName());
                 }
                 @Override
                 public Content visitArray(List vals, Void p) {
    @@ -2304,7 +2269,7 @@ private Content withLinks(String key, String className, Set element
             elements.stream()
                     .sorted((te1, te2) -> te1.getSimpleName().toString().compareTo(te2.getSimpleName().toString()))
                     .distinct()
    -                .map(te -> getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.CLASS, te).label(HtmlTree.CODE(new StringContent(te.getSimpleName()))).skipPreview(true)))
    +                .map(te -> getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.CLASS, te).label(HtmlTree.CODE(new StringContent(te.getSimpleName()))).skipPreview(true)))
                     .forEach(c -> {
                         links.add(sep[0]);
                         links.add(c);
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java
    similarity index 84%
    rename from src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java
    rename to src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java
    index e78e340d9b7..4c4c1759ce4 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkFactoryImpl.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java
    @@ -39,7 +39,6 @@
     import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
     import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
     import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
    -import jdk.javadoc.internal.doclets.formats.html.markup.TagName;
     import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
     import jdk.javadoc.internal.doclets.toolkit.Content;
     import jdk.javadoc.internal.doclets.toolkit.Resources;
    @@ -58,12 +57,12 @@
      *  This code and its internal interfaces are subject to change or
      *  deletion without notice.
      */
    -public class LinkFactoryImpl extends LinkFactory {
    +public class HtmlLinkFactory extends LinkFactory {
     
         private final HtmlDocletWriter m_writer;
         private final DocPaths docPaths;
     
    -    public LinkFactoryImpl(HtmlDocletWriter writer) {
    +    public HtmlLinkFactory(HtmlDocletWriter writer) {
             super(writer.configuration.utils);
             m_writer = writer;
             docPaths = writer.configuration.docPaths;
    @@ -77,8 +76,7 @@ protected Content newContent() {
         @Override
         protected Content getClassLink(LinkInfo linkInfo) {
             BaseConfiguration configuration = m_writer.configuration;
    -        LinkInfoImpl classLinkInfo = (LinkInfoImpl) linkInfo;
    -        boolean noLabel = linkInfo.label == null || linkInfo.label.isEmpty();
    +        HtmlLinkInfo classLinkInfo = (HtmlLinkInfo) linkInfo;
             TypeElement typeElement = classLinkInfo.typeElement;
             // Create a tool tip if we are linking to a class or interface.  Don't
             // create one if we are linking to a member.
    @@ -96,7 +94,7 @@ protected Content getClassLink(LinkInfo linkInfo) {
             if (!hasWhere && showPreview) {
                 flags = utils.elementFlags(typeElement);
                 target = typeElement;
    -        } else if ((classLinkInfo.context == LinkInfoImpl.Kind.SEE_TAG || classLinkInfo.context == LinkInfoImpl.Kind.MEMBER_DEPRECATED_PREVIEW) &&
    +        } else if ((classLinkInfo.context == HtmlLinkInfo.Kind.SEE_TAG || classLinkInfo.context == HtmlLinkInfo.Kind.MEMBER_DEPRECATED_PREVIEW) &&
                        classLinkInfo.targetMember != null && showPreview) {
                 flags = utils.elementFlags(classLinkInfo.targetMember);
                 target = classLinkInfo.targetMember;
    @@ -107,30 +105,27 @@ protected Content getClassLink(LinkInfo linkInfo) {
     
             Content link = new ContentBuilder();
             if (utils.isIncluded(typeElement)) {
    -            if (configuration.isGeneratedDoc(typeElement)) {
    +            if (configuration.isGeneratedDoc(typeElement) && !utils.hasHiddenTag(typeElement)) {
                     DocPath filename = getPath(classLinkInfo);
                     if (linkInfo.linkToSelf ||
                                     !(docPaths.forName(typeElement)).equals(m_writer.filename)) {
                             link.add(m_writer.links.createLink(
                                     filename.fragment(classLinkInfo.where),
                                     label,
    -                                classLinkInfo.isStrong,
    +                                classLinkInfo.style,
                                     title));
                             if (flags.contains(ElementFlag.PREVIEW)) {
                                 link.add(HtmlTree.SUP(m_writer.links.createLink(
                                         filename.fragment(m_writer.htmlIds.forPreviewSection(target).name()),
                                         m_writer.contents.previewMark)));
                             }
    -                        if (noLabel && !classLinkInfo.excludeTypeParameterLinks) {
    -                            link.add(getTypeParameterLinks(linkInfo));
    -                        }
                             return link;
                     }
                 }
             } else {
                 Content crossLink = m_writer.getCrossClassLink(
                     typeElement, classLinkInfo.where,
    -                label, classLinkInfo.isStrong, true);
    +                label, classLinkInfo.style, true);
                 if (crossLink != null) {
                     link.add(crossLink);
                     if (flags.contains(ElementFlag.PREVIEW)) {
    @@ -138,10 +133,7 @@ protected Content getClassLink(LinkInfo linkInfo) {
                             typeElement,
                             m_writer.htmlIds.forPreviewSection(target).name(),
                             m_writer.contents.previewMark,
    -                        false, false)));
    -                }
    -                if (noLabel && !classLinkInfo.excludeTypeParameterLinks) {
    -                    link.add(getTypeParameterLinks(linkInfo));
    +                        null, false)));
                     }
                     return link;
                 }
    @@ -151,14 +143,11 @@ protected Content getClassLink(LinkInfo linkInfo) {
             if (flags.contains(ElementFlag.PREVIEW)) {
                 link.add(HtmlTree.SUP(m_writer.contents.previewMark));
             }
    -        if (noLabel && !classLinkInfo.excludeTypeParameterLinks) {
    -            link.add(getTypeParameterLinks(linkInfo));
    -        }
             return link;
         }
     
         @Override
    -    protected Content getTypeParameterLinks(LinkInfo linkInfo, boolean isClassLabel) {
    +    protected Content getTypeParameterLinks(LinkInfo linkInfo) {
             Content links = newContent();
             List vars = new ArrayList<>();
             TypeMirror ctype = linkInfo.type != null
    @@ -176,15 +165,14 @@ protected Content getTypeParameterLinks(LinkInfo linkInfo, boolean isClassLabel)
                 // Nothing to document.
                 return links;
             }
    -        if (((linkInfo.includeTypeInClassLinkLabel && isClassLabel)
    -                || (linkInfo.includeTypeAsSepLink && !isClassLabel)) && !vars.isEmpty()) {
    +        if (!vars.isEmpty()) {
                 links.add("<");
                 boolean many = false;
                 for (TypeMirror t : vars) {
                     if (many) {
                         links.add(",");
                         links.add(Entity.ZERO_WIDTH_SPACE);
    -                    if (((LinkInfoImpl) linkInfo).getContext() == LinkInfoImpl.Kind.MEMBER_TYPE_PARAMS) {
    +                    if (((HtmlLinkInfo) linkInfo).getContext() == HtmlLinkInfo.Kind.MEMBER_TYPE_PARAMS) {
                             links.add(DocletConstants.NL);
                         }
                     }
    @@ -204,8 +192,8 @@ protected Content getTypeParameterLinks(LinkInfo linkInfo, boolean isClassLabel)
          * @return the link
          */
         protected Content getTypeParameterLink(LinkInfo linkInfo, TypeMirror typeParam) {
    -        LinkInfoImpl typeLinkInfo = new LinkInfoImpl(m_writer.configuration,
    -                ((LinkInfoImpl) linkInfo).getContext(), typeParam).skipPreview(true);
    +        HtmlLinkInfo typeLinkInfo = new HtmlLinkInfo(m_writer.configuration,
    +                ((HtmlLinkInfo) linkInfo).getContext(), typeParam).skipPreview(true);
             typeLinkInfo.excludeTypeBounds = linkInfo.excludeTypeBounds;
             typeLinkInfo.excludeTypeParameterLinks = linkInfo.excludeTypeParameterLinks;
             typeLinkInfo.linkToSelf = linkInfo.linkToSelf;
    @@ -221,7 +209,7 @@ public Content getTypeAnnotationLinks(LinkInfo linkInfo) {
             } else if (utils.isTypeVariable(linkInfo.type)) {
                 // TODO: use the context for now, and special case for Receiver_Types,
                 // which takes the default case.
    -            switch (((LinkInfoImpl)linkInfo).context) {
    +            switch (((HtmlLinkInfo)linkInfo).context) {
                     case MEMBER_TYPE_PARAMS:
                     case EXECUTABLE_MEMBER_PARAM:
                     case CLASS_SIGNATURE:
    @@ -283,12 +271,7 @@ private String getClassToolTip(TypeElement typeElement, boolean isTypeLink) {
          *
          * @param linkInfo the information about the link.
          */
    -    private DocPath getPath(LinkInfoImpl linkInfo) {
    -        if (linkInfo.context == LinkInfoImpl.Kind.PACKAGE_FRAME) {
    -            //Not really necessary to do this but we want to be consistent
    -            //with 1.4.2 output.
    -            return docPaths.forName(linkInfo.typeElement);
    -        }
    +    private DocPath getPath(HtmlLinkInfo linkInfo) {
             return m_writer.pathToRoot.resolve(docPaths.forClass(linkInfo.typeElement));
         }
     }
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkInfo.java
    similarity index 84%
    rename from src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java
    rename to src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkInfo.java
    index f00087cff65..91f264f2b0c 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkInfo.java
    @@ -31,6 +31,7 @@
     import javax.lang.model.type.TypeMirror;
     
     import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
    +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
     import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
     import jdk.javadoc.internal.doclets.toolkit.Content;
     import jdk.javadoc.internal.doclets.toolkit.util.Utils;
    @@ -43,7 +44,7 @@
      *  This code and its internal interfaces are subject to change or
      *  deletion without notice.
      */
    -public class LinkInfoImpl extends LinkInfo {
    +public class HtmlLinkInfo extends LinkInfo {
     
         public enum Kind {
             DEFAULT,
    @@ -108,11 +109,6 @@ public enum Kind {
              */
             TREE,
     
    -        /**
    -         * Indicate that the link appears in a class list.
    -         */
    -        PACKAGE_FRAME,
    -
             /**
              * The header in the class documentation.
              */
    @@ -246,7 +242,13 @@ public enum Kind {
          */
         public Element targetMember;
     
    -    public  final Utils utils;
    +    /**
    +     * Optional style for the link.
    +     */
    +    public HtmlStyle style = null;
    +
    +    public final Utils utils;
    +
         /**
          * Construct a LinkInfo object.
          *
    @@ -254,7 +256,7 @@ public enum Kind {
          * @param context    the context of the link.
          * @param ee   the member to link to.
          */
    -    public LinkInfoImpl(HtmlConfiguration configuration, Kind context, ExecutableElement ee) {
    +    public HtmlLinkInfo(HtmlConfiguration configuration, Kind context, ExecutableElement ee) {
             this.configuration = configuration;
             this.utils = configuration.utils;
             this.executableElement = ee;
    @@ -273,7 +275,7 @@ protected Content newContent() {
          * @param context    the context of the link.
          * @param typeElement   the class to link to.
          */
    -    public LinkInfoImpl(HtmlConfiguration configuration, Kind context, TypeElement typeElement) {
    +    public HtmlLinkInfo(HtmlConfiguration configuration, Kind context, TypeElement typeElement) {
             this.configuration = configuration;
             this.utils = configuration.utils;
             this.typeElement = typeElement;
    @@ -287,7 +289,7 @@ public LinkInfoImpl(HtmlConfiguration configuration, Kind context, TypeElement t
          * @param context    the context of the link.
          * @param type       the class to link to.
          */
    -    public LinkInfoImpl(HtmlConfiguration configuration, Kind context, TypeMirror type) {
    +    public HtmlLinkInfo(HtmlConfiguration configuration, Kind context, TypeMirror type) {
             this.configuration = configuration;
             this.utils = configuration.utils;
             this.type = type;
    @@ -298,7 +300,7 @@ public LinkInfoImpl(HtmlConfiguration configuration, Kind context, TypeMirror ty
          * Set the label for the link.
          * @param label plain-text label for the link
          */
    -    public LinkInfoImpl label(CharSequence label) {
    +    public HtmlLinkInfo label(CharSequence label) {
             this.label = new StringContent(label);
             return this;
         }
    @@ -306,23 +308,23 @@ public LinkInfoImpl label(CharSequence label) {
         /**
          * Set the label for the link.
          */
    -    public LinkInfoImpl label(Content label) {
    +    public HtmlLinkInfo label(Content label) {
             this.label = label;
             return this;
         }
     
         /**
    -     * Set whether or not the link should be strong.
    +     * Sets the style to be used for the link.
          */
    -    public LinkInfoImpl strong(boolean strong) {
    -        this.isStrong = strong;
    +    public HtmlLinkInfo style(HtmlStyle style) {
    +        this.style = style;
             return this;
         }
     
         /**
          * Set whether or not this is a link to a varargs parameter.
          */
    -    public LinkInfoImpl varargs(boolean varargs) {
    +    public HtmlLinkInfo varargs(boolean varargs) {
             this.isVarArg = varargs;
             return this;
         }
    @@ -330,7 +332,7 @@ public LinkInfoImpl varargs(boolean varargs) {
         /**
          * Set the fragment specifier for the link.
          */
    -    public LinkInfoImpl where(String where) {
    +    public HtmlLinkInfo where(String where) {
             this.where = where;
             return this;
         }
    @@ -338,7 +340,7 @@ public LinkInfoImpl where(String where) {
         /**
          * Set the member this link points to (if any).
          */
    -    public LinkInfoImpl targetMember(Element el) {
    +    public HtmlLinkInfo targetMember(Element el) {
             this.targetMember = el;
             return this;
         }
    @@ -346,7 +348,7 @@ public LinkInfoImpl targetMember(Element el) {
         /**
          * Set whether or not the preview flags should be skipped for this link.
          */
    -    public LinkInfoImpl skipPreview(boolean skipPreview) {
    +    public HtmlLinkInfo skipPreview(boolean skipPreview) {
             this.skipPreview = skipPreview;
             return this;
         }
    @@ -362,22 +364,8 @@ public Kind getContext() {
          * @param c the context id to set.
          */
         public final void setContext(Kind c) {
    -        //NOTE:  Put context specific link code here.
             switch (c) {
    -            case PACKAGE_FRAME:
    -            case IMPLEMENTED_CLASSES:
    -            case SUBCLASSES:
    -            case EXECUTABLE_ELEMENT_COPY:
    -            case PROPERTY_COPY:
    -            case CLASS_USE_HEADER:
    -                includeTypeInClassLinkLabel = false;
    -                break;
    -
                 case ANNOTATION:
    -                excludeTypeParameterLinks = true;
    -                excludeTypeBounds = true;
    -                break;
    -
                 case IMPLEMENTED_INTERFACES:
                 case SUPER_INTERFACES:
                 case SUBINTERFACES:
    @@ -387,8 +375,6 @@ public final void setContext(Kind c) {
                 case PERMITTED_SUBCLASSES:
                     excludeTypeParameterLinks = true;
                     excludeTypeBounds = true;
    -                includeTypeInClassLinkLabel = false;
    -                includeTypeAsSepLink = true;
                     break;
     
                 case PACKAGE:
    @@ -397,13 +383,6 @@ public final void setContext(Kind c) {
                 case CLASS_SIGNATURE:
                 case RECEIVER_TYPE:
                     excludeTypeParameterLinks = true;
    -                includeTypeAsSepLink = true;
    -                includeTypeInClassLinkLabel = false;
    -                break;
    -
    -            case MEMBER_TYPE_PARAMS:
    -                includeTypeAsSepLink = true;
    -                includeTypeInClassLinkLabel = false;
                     break;
     
                 case RETURN_TYPE:
    @@ -414,11 +393,6 @@ public final void setContext(Kind c) {
                     break;
             }
             context = c;
    -        if (type != null &&
    -            utils.isTypeVariable(type) &&
    -            utils.isExecutableElement(utils.asTypeElement(type).getEnclosingElement())) {
    -                excludeTypeParameterLinks = true;
    -        }
         }
     
         /**
    @@ -433,11 +407,39 @@ public boolean isLinkable() {
             return configuration.utils.isLinkable(typeElement);
         }
     
    +    @Override
    +    public boolean includeTypeParameterLinks() {
    +        return switch (context) {
    +            case IMPLEMENTED_INTERFACES,
    +                 SUPER_INTERFACES,
    +                 SUBINTERFACES,
    +                 CLASS_TREE_PARENT,
    +                 TREE,
    +                 CLASS_SIGNATURE_PARENT_NAME,
    +                 PERMITTED_SUBCLASSES,
    +                 PACKAGE,
    +                 CLASS_USE,
    +                 CLASS_HEADER,
    +                 CLASS_SIGNATURE,
    +                 RECEIVER_TYPE,
    +                 MEMBER_TYPE_PARAMS -> true;
    +
    +            case IMPLEMENTED_CLASSES,
    +                 SUBCLASSES,
    +                 EXECUTABLE_ELEMENT_COPY,
    +                 PROPERTY_COPY,
    +                 CLASS_USE_HEADER -> false;
    +
    +            default -> label == null || label.isEmpty();
    +        };
    +    }
    +
         @Override
         public String toString() {
    -        return "LinkInfoImpl{" +
    +        return "HtmlLinkInfo{" +
                     "context=" + context +
                     ", where=" + where +
    +                ", style=" + style +
                     super.toString() + '}';
         }
     }
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java
    index 039b3d45550..242b23d08dd 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -34,7 +34,6 @@
     import com.sun.source.doctree.DocTree;
     
     import com.sun.source.doctree.SerialTree;
    -import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
     import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
     import jdk.javadoc.internal.doclets.formats.html.markup.TagName;
     import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
    @@ -42,7 +41,6 @@
     import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
     import jdk.javadoc.internal.doclets.toolkit.Content;
     import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter;
    -import jdk.javadoc.internal.doclets.toolkit.taglets.TagletWriter;
     import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
     
     /**
    @@ -121,8 +119,8 @@ public void addMemberHeader(TypeElement fieldType, String fieldTypeStr,
             if (fieldType == null) {
                 pre.add(fieldTypeStr);
             } else {
    -            Content fieldContent = writer.getLink(new LinkInfoImpl(
    -                    configuration, LinkInfoImpl.Kind.SERIAL_MEMBER, fieldType));
    +            Content fieldContent = writer.getLink(new HtmlLinkInfo(
    +                    configuration, HtmlLinkInfo.Kind.SERIAL_MEMBER, fieldType));
                 pre.add(fieldContent);
             }
             pre.add(fieldDimensions + " ");
    @@ -136,8 +134,8 @@ public void addMemberHeader(TypeMirror fieldType, String fieldName, Content cont
             Content heading = HtmlTree.HEADING(TagName.H5, nameContent);
             contentTree.add(heading);
             Content pre = new HtmlTree(TagName.PRE);
    -        Content fieldContent = writer.getLink(new LinkInfoImpl(
    -                configuration, LinkInfoImpl.Kind.SERIAL_MEMBER, fieldType));
    +        Content fieldContent = writer.getLink(new HtmlLinkInfo(
    +                configuration, HtmlLinkInfo.Kind.SERIAL_MEMBER, fieldType));
             pre.add(fieldContent);
             pre.add(" ");
             pre.add(fieldName);
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexWriter.java
    index a6f1cb8c09a..f88c74c1af8 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexWriter.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/IndexWriter.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -214,8 +214,8 @@ protected void addElementDescription(IndexItem item, Content dlTree) {
                 case RECORD:
                 case ANNOTATION_TYPE:
                 case INTERFACE:
    -                dt = HtmlTree.DT(getLink(new LinkInfoImpl(configuration,
    -                        LinkInfoImpl.Kind.INDEX, (TypeElement) element).strong(true)));
    +                dt = HtmlTree.DT(getLink(new HtmlLinkInfo(configuration,
    +                        HtmlLinkInfo.Kind.INDEX, (TypeElement) element).style(HtmlStyle.typeNameLink)));
                     dt.add(" - ");
                     addClassInfo((TypeElement) element, dt);
                     break;
    @@ -225,8 +225,8 @@ protected void addElementDescription(IndexItem item, Content dlTree) {
                 case FIELD:
                 case ENUM_CONSTANT:
                     TypeElement containingType = item.getContainingTypeElement();
    -                dt = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.memberNameLink,
    -                        getDocLink(LinkInfoImpl.Kind.INDEX, containingType, element, new StringContent(label))));
    +                dt = HtmlTree.DT(getDocLink(HtmlLinkInfo.Kind.INDEX, containingType, element,
    +                                label, HtmlStyle.memberNameLink));
                     dt.add(" - ");
                     addMemberDesc(element, containingType, dt);
                     break;
    @@ -268,7 +268,7 @@ protected void addTagDescription(IndexItem item, Content dlTree) {
             String itemPath = pathToRoot.isEmpty() ? "" : pathToRoot.getPath() + "/";
             itemPath += item.getUrl();
             HtmlTree labelLink = HtmlTree.A(itemPath, new StringContent(item.getLabel()));
    -        Content dt = HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.searchTagLink, labelLink));
    +        Content dt = HtmlTree.DT(labelLink.setStyle(HtmlStyle.searchTagLink));
             dt.add(" - ");
             dt.add(contents.getContent("doclet.Search_tag_in", item.getHolder()));
             dlTree.add(dt);
    @@ -338,8 +338,8 @@ protected void addMemberDesc(Element member, TypeElement enclosing, Content cont
                 default -> throw new IllegalArgumentException(member.getKind().toString());
             };
             contentTree.add(contents.getContent(resource, kindName)).add(" ");
    -        addPreQualifiedClassLink(LinkInfoImpl.Kind.INDEX, enclosing,
    -                false, contentTree);
    +        addPreQualifiedClassLink(HtmlLinkInfo.Kind.INDEX, enclosing,
    +                null, contentTree);
         }
     
         /**
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java
    index 80b0783f4a3..7a28be7282d 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java
    @@ -149,21 +149,22 @@ public void addComments(TypeMirror holderType, ExecutableElement method, Content
                         utils.isLinkable(holder))) {
                     writer.addInlineComment(method, methodDocTree);
                 } else {
    -                Content link =
    -                        writer.getDocLink(LinkInfoImpl.Kind.EXECUTABLE_ELEMENT_COPY,
    -                        holder, method,
    -                        utils.isIncluded(holder)
    -                                ? utils.getSimpleName(holder)
    -                                : utils.getFullyQualifiedName(holder),
    -                            false);
    -                Content codeLink = HtmlTree.CODE(link);
    -                Content descfrmLabel = HtmlTree.SPAN(HtmlStyle.descfrmTypeLabel,
    -                        utils.isClass(holder)
    -                                ? contents.descfrmClassLabel
    -                                : contents.descfrmInterfaceLabel);
    -                descfrmLabel.add(Entity.NO_BREAK_SPACE);
    -                descfrmLabel.add(codeLink);
    -                methodDocTree.add(HtmlTree.DIV(HtmlStyle.block, descfrmLabel));
    +                if (!utils.hasHiddenTag(holder) && !utils.hasHiddenTag(method)) {
    +                    Content link =
    +                            writer.getDocLink(HtmlLinkInfo.Kind.EXECUTABLE_ELEMENT_COPY,
    +                                    holder, method,
    +                                    utils.isIncluded(holder)
    +                                            ? utils.getSimpleName(holder)
    +                                            : utils.getFullyQualifiedName(holder));
    +                    Content codeLink = HtmlTree.CODE(link);
    +                    Content descfrmLabel = HtmlTree.SPAN(HtmlStyle.descfrmTypeLabel,
    +                            utils.isClass(holder)
    +                                    ? contents.descfrmClassLabel
    +                                    : contents.descfrmInterfaceLabel);
    +                    descfrmLabel.add(Entity.NO_BREAK_SPACE);
    +                    descfrmLabel.add(codeLink);
    +                    methodDocTree.add(HtmlTree.DIV(HtmlStyle.block, descfrmLabel));
    +                }
                     writer.addInlineComment(method, methodDocTree);
                 }
             }
    @@ -214,7 +215,7 @@ protected Table createSummaryTable() {
         @Override
         public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) {
             Content classLink = writer.getPreQualifiedClassLink(
    -                LinkInfoImpl.Kind.MEMBER, typeElement, false);
    +                HtmlLinkInfo.Kind.MEMBER, typeElement);
             Content label;
             if (options.summarizeOverriddenMethods()) {
                 label = new StringContent(utils.isClass(typeElement)
    @@ -266,36 +267,37 @@ protected static void addOverridden(HtmlDocletWriter writer,
                 //is not visible so don't document this.
                 return;
             }
    +        if (utils.hasHiddenTag(holder) || utils.hasHiddenTag(method)) {
    +            return;
    +        }
     
    -        if (method != null) {
    -            Contents contents = writer.contents;
    -            Content label;
    -            LinkInfoImpl.Kind context;
    -            if (utils.isAbstract(holder) && utils.isAbstract(method)){
    -                //Abstract method is implemented from abstract class,
    -                //not overridden
    -                label = contents.specifiedByLabel;
    -                context = LinkInfoImpl.Kind.METHOD_SPECIFIED_BY;
    -            } else {
    -                label = contents.overridesLabel;
    -                context = LinkInfoImpl.Kind.METHOD_OVERRIDES;
    -            }
    -            dl.add(HtmlTree.DT(label));
    -            Content overriddenTypeLink =
    -                    writer.getLink(new LinkInfoImpl(writer.configuration, context, overriddenType));
    -            Content codeOverriddenTypeLink = HtmlTree.CODE(overriddenTypeLink);
    -            Content methlink = writer.getLink(
    -                    new LinkInfoImpl(writer.configuration, LinkInfoImpl.Kind.MEMBER, holder)
    -                            .where(writer.htmlIds.forMember(method).name())
    -                            .label(method.getSimpleName()));
    -            Content codeMethLink = HtmlTree.CODE(methlink);
    -            Content dd = HtmlTree.DD(codeMethLink);
    -            dd.add(Entity.NO_BREAK_SPACE);
    -            dd.add(contents.inClass);
    -            dd.add(Entity.NO_BREAK_SPACE);
    -            dd.add(codeOverriddenTypeLink);
    -            dl.add(dd);
    +        Contents contents = writer.contents;
    +        Content label;
    +        HtmlLinkInfo.Kind context;
    +        if (utils.isAbstract(holder) && utils.isAbstract(method)) {
    +            //Abstract method is implemented from abstract class,
    +            //not overridden
    +            label = contents.specifiedByLabel;
    +            context = HtmlLinkInfo.Kind.METHOD_SPECIFIED_BY;
    +        } else {
    +            label = contents.overridesLabel;
    +            context = HtmlLinkInfo.Kind.METHOD_OVERRIDES;
             }
    +        dl.add(HtmlTree.DT(label));
    +        Content overriddenTypeLink =
    +                writer.getLink(new HtmlLinkInfo(writer.configuration, context, overriddenType));
    +        Content codeOverriddenTypeLink = HtmlTree.CODE(overriddenTypeLink);
    +        Content methlink = writer.getLink(
    +                new HtmlLinkInfo(writer.configuration, HtmlLinkInfo.Kind.MEMBER, holder)
    +                        .where(writer.htmlIds.forMember(method).name())
    +                        .label(method.getSimpleName()));
    +        Content codeMethLink = HtmlTree.CODE(methlink);
    +        Content dd = HtmlTree.DD(codeMethLink);
    +        dd.add(Entity.NO_BREAK_SPACE);
    +        dd.add(contents.inClass);
    +        dd.add(Entity.NO_BREAK_SPACE);
    +        dd.add(codeOverriddenTypeLink);
    +        dl.add(dd);
         }
     
         /**
    @@ -322,13 +324,13 @@ protected static void addImplementsInfo(HtmlDocletWriter writer,
             for (ExecutableElement implementedMeth : implementedMethods) {
                 TypeMirror intfac = vmt.getImplementedMethodHolder(method, implementedMeth);
                 intfac = utils.getDeclaredType(utils.getEnclosingTypeElement(method), intfac);
    -            Content intfaclink = writer.getLink(new LinkInfoImpl(
    -                    writer.configuration, LinkInfoImpl.Kind.METHOD_SPECIFIED_BY, intfac));
    +            Content intfaclink = writer.getLink(new HtmlLinkInfo(
    +                    writer.configuration, HtmlLinkInfo.Kind.METHOD_SPECIFIED_BY, intfac));
                 Content codeIntfacLink = HtmlTree.CODE(intfaclink);
                 dl.add(HtmlTree.DT(contents.specifiedByLabel));
                 Content methlink = writer.getDocLink(
    -                    LinkInfoImpl.Kind.MEMBER, implementedMeth,
    -                    implementedMeth.getSimpleName(), false);
    +                    HtmlLinkInfo.Kind.MEMBER, implementedMeth,
    +                    implementedMeth.getSimpleName());
                 Content codeMethLink = HtmlTree.CODE(methlink);
                 Content dd = HtmlTree.DD(codeMethLink);
                 dd.add(Entity.NO_BREAK_SPACE);
    @@ -348,7 +350,7 @@ protected static void addImplementsInfo(HtmlDocletWriter writer,
         protected Content getReturnType(ExecutableElement method) {
             TypeMirror type = utils.getReturnType(typeElement, method);
             if (type != null) {
    -            return writer.getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.RETURN_TYPE, type));
    +            return writer.getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.RETURN_TYPE, type));
             }
             return new ContentBuilder();
         }
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
    index 1ce1933e322..9a1f464277d 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java
    @@ -726,7 +726,7 @@ public void addUsesList(Table table) {
                 if (!displayServiceDirective(t, usesTrees)) {
                     continue;
                 }
    -            typeLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, t));
    +            typeLinkContent = getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.PACKAGE, t));
                 Content summary = new ContentBuilder();
                 if (display(usesTrees)) {
                     description = usesTrees.get(t);
    @@ -756,7 +756,7 @@ public void addProvidesList(Table table) {
                     continue;
                 }
                 implSet = entry.getValue();
    -            Content srvLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, srv));
    +            Content srvLinkContent = getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.PACKAGE, srv));
                 Content desc = new ContentBuilder();
                 if (display(providesTrees)) {
                     description = providesTrees.get(srv);
    @@ -776,7 +776,7 @@ public void addProvidesList(Table table) {
                     String sep = "";
                     for (TypeElement impl : implSet) {
                         desc.add(sep);
    -                    desc.add(getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, impl)));
    +                    desc.add(getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.PACKAGE, impl)));
                         sep = ", ";
                     }
                     desc.add(")");
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java
    index 54d1add708d..0d7b09884f8 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/NestedClassWriterImpl.java
    @@ -101,8 +101,7 @@ protected Table createSummaryTable() {
     
         @Override
         public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) {
    -        Content classLink = writer.getPreQualifiedClassLink(
    -                LinkInfoImpl.Kind.MEMBER, typeElement, false);
    +        Content classLink = writer.getPreQualifiedClassLink(HtmlLinkInfo.Kind.MEMBER, typeElement);
             Content label;
             if (options.summarizeOverriddenMethods()) {
                 label = new StringContent(utils.isInterface(typeElement)
    @@ -121,10 +120,10 @@ public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedT
         }
     
         @Override
    -    protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element member,
    -            Content tdSummary) {
    -        Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink,
    -                writer.getLink(new LinkInfoImpl(configuration, context, (TypeElement)member)));
    +    protected void addSummaryLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Element member,
    +                                  Content tdSummary) {
    +        Content memberLink = writer.getLink(new HtmlLinkInfo(configuration, context, (TypeElement)member)
    +                .style(HtmlStyle.typeNameLink));
             Content code = HtmlTree.CODE(memberLink);
             tdSummary.add(code);
         }
    @@ -132,7 +131,7 @@ protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement typeElement
         @Override
         protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content linksTree) {
             linksTree.add(
    -                writer.getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER,
    +                writer.getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.MEMBER,
                             (TypeElement)member)));
         }
     
    @@ -143,6 +142,6 @@ protected void addSummaryType(Element member, Content tdSummaryType) {
     
         @Override
         protected Content getSummaryLink(Element member) {
    -        return writer.getQualifiedClassLink(LinkInfoImpl.Kind.MEMBER_DEPRECATED_PREVIEW, member);
    +        return writer.getQualifiedClassLink(HtmlLinkInfo.Kind.MEMBER_DEPRECATED_PREVIEW, member);
         }
     }
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
    index 31e5bf5411b..2661d415c5e 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java
    @@ -213,8 +213,8 @@ public void addClassesSummary(SortedSet classes, String label,
                     if (!utils.isCoreClass(klass) || !configuration.isGeneratedDoc(klass)) {
                         continue;
                     }
    -                Content classLink = getLink(new LinkInfoImpl(
    -                        configuration, LinkInfoImpl.Kind.PACKAGE, klass));
    +                Content classLink = getLink(new HtmlLinkInfo(
    +                        configuration, HtmlLinkInfo.Kind.PACKAGE, klass));
                     ContentBuilder description = new ContentBuilder();
                     addPreviewSummary(klass, description);
                     if (utils.isDeprecated(klass)) {
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java
    index 97368b4616a..e4e11c130c3 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java
    @@ -111,20 +111,21 @@ public void addComments(ExecutableElement property, Content propertyDocTree) {
                         (!utils.isPublic(holder) || utils.isLinkable(holder))) {
                     writer.addInlineComment(property, propertyDocTree);
                 } else {
    -                Content link =
    -                        writer.getDocLink(LinkInfoImpl.Kind.PROPERTY_COPY,
    -                        holder, property,
    -                        utils.isIncluded(holder)
    -                                ? holder.getSimpleName() : holder.getQualifiedName(),
    -                            false);
    -                Content codeLink = HtmlTree.CODE(link);
    -                Content descfrmLabel = HtmlTree.SPAN(HtmlStyle.descfrmTypeLabel,
    -                        utils.isClass(holder)
    -                                ? contents.descfrmClassLabel
    -                                : contents.descfrmInterfaceLabel);
    -                descfrmLabel.add(Entity.NO_BREAK_SPACE);
    -                descfrmLabel.add(codeLink);
    -                propertyDocTree.add(HtmlTree.DIV(HtmlStyle.block, descfrmLabel));
    +                if (!utils.hasHiddenTag(holder) && !utils.hasHiddenTag(property)) {
    +                    Content link =
    +                            writer.getDocLink(HtmlLinkInfo.Kind.PROPERTY_COPY,
    +                                    holder, property,
    +                                    utils.isIncluded(holder)
    +                                            ? holder.getSimpleName() : holder.getQualifiedName());
    +                    Content codeLink = HtmlTree.CODE(link);
    +                    Content descfrmLabel = HtmlTree.SPAN(HtmlStyle.descfrmTypeLabel,
    +                            utils.isClass(holder)
    +                                    ? contents.descfrmClassLabel
    +                                    : contents.descfrmInterfaceLabel);
    +                    descfrmLabel.add(Entity.NO_BREAK_SPACE);
    +                    descfrmLabel.add(codeLink);
    +                    propertyDocTree.add(HtmlTree.DIV(HtmlStyle.block, descfrmLabel));
    +                }
                     writer.addInlineComment(property, propertyDocTree);
                 }
             }
    @@ -168,7 +169,7 @@ protected Table createSummaryTable() {
         @Override
         public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedTree) {
             Content classLink = writer.getPreQualifiedClassLink(
    -                LinkInfoImpl.Kind.MEMBER, typeElement, false);
    +                HtmlLinkInfo.Kind.MEMBER, typeElement);
             Content label;
             if (options.summarizeOverriddenMethods()) {
                 label = new StringContent(utils.isClass(typeElement)
    @@ -188,14 +189,13 @@ public void addInheritedSummaryLabel(TypeElement typeElement, Content inheritedT
         }
     
         @Override
    -    protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element member,
    -            Content tdSummary) {
    -        Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink,
    -                writer.getDocLink(context, typeElement,
    +    protected void addSummaryLink(HtmlLinkInfo.Kind context, TypeElement typeElement, Element member,
    +                                  Content tdSummary) {
    +        Content memberLink = writer.getDocLink(context, typeElement,
                     member,
    -                utils.getPropertyLabel(name(member)),
    -                false,
    -                true));
    +                new StringContent(utils.getPropertyLabel(name(member))),
    +                HtmlStyle.memberNameLink,
    +                true);
     
             Content code = HtmlTree.CODE(memberLink);
             tdSummary.add(code);
    @@ -204,9 +204,8 @@ protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement typeElement
         @Override
         protected void addInheritedSummaryLink(TypeElement typeElement, Element member, Content linksTree) {
             String mname = name(member);
    -        Content content = writer.getDocLink(LinkInfoImpl.Kind.MEMBER, typeElement, member,
    -                utils.isProperty(mname) ? utils.getPropertyName(mname) : mname,
    -                false, true);
    +        Content content = writer.getDocLink(HtmlLinkInfo.Kind.MEMBER, typeElement, member,
    +                utils.isProperty(mname) ? utils.getPropertyName(mname) : mname, true);
             linksTree.add(content);
         }
     
    @@ -217,7 +216,7 @@ protected void addSummaryType(Element member, Content tdSummaryType) {
     
         @Override
         protected Content getSummaryLink(Element member) {
    -        return writer.getDocLink(LinkInfoImpl.Kind.MEMBER_DEPRECATED_PREVIEW, member,
    +        return writer.getDocLink(HtmlLinkInfo.Kind.MEMBER_DEPRECATED_PREVIEW, member,
                     utils.getFullyQualifiedName(member));
         }
     
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java
    index a71b9957fc2..fac5e2ff126 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SerializedFormWriterImpl.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -137,7 +137,8 @@ public Content getClassSerializedHeader() {
          * @return true if the class, that is being processed, is generated and is visible.
          */
         public boolean isVisibleClass(TypeElement typeElement) {
    -        return visibleClasses.contains(typeElement) && configuration.isGeneratedDoc(typeElement);
    +        return visibleClasses.contains(typeElement) && configuration.isGeneratedDoc(typeElement)
    +                && !utils.hasHiddenTag(typeElement);
         }
     
         /**
    @@ -149,13 +150,13 @@ public boolean isVisibleClass(TypeElement typeElement) {
         @Override
         public Content getClassHeader(TypeElement typeElement) {
             Content classLink = (isVisibleClass(typeElement))
    -                ? getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.DEFAULT, typeElement)
    +                ? getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.DEFAULT, typeElement)
                             .label(configuration.getClassName(typeElement)))
                     : new StringContent(utils.getFullyQualifiedName(typeElement));
             Content section = HtmlTree.SECTION(HtmlStyle.serializedClassDetails)
                     .setId(htmlIds.forClass(typeElement));
             Content superClassLink = typeElement.getSuperclass() != null
    -                ? getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.SERIALIZED_FORM,
    +                ? getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.SERIALIZED_FORM,
                             typeElement.getSuperclass()))
                     : null;
     
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Signatures.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Signatures.java
    index 562f2910afd..dafd39440c9 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Signatures.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Signatures.java
    @@ -1,3 +1,28 @@
    +/*
    + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
    + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    + *
    + * This code is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU General Public License version 2 only, as
    + * published by the Free Software Foundation.  Oracle designates this
    + * particular file as subject to the "Classpath" exception as provided
    + * by Oracle in the LICENSE file that accompanied this code.
    + *
    + * This code is distributed in the hope that it will be useful, but WITHOUT
    + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    + * version 2 for more details (a copy is included in the LICENSE file that
    + * accompanied this code).
    + *
    + * You should have received a copy of the GNU General Public License version
    + * 2 along with this work; if not, write to the Free Software Foundation,
    + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    + *
    + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    + * or visit www.oracle.com if you need additional information or have any
    + * questions.
    + */
    +
     package jdk.javadoc.internal.doclets.formats.html;
     
     import jdk.javadoc.doclet.DocletEnvironment;
    @@ -97,8 +122,8 @@ public Content toContent() {
                 } else {
                     nameSpan.addStyle(HtmlStyle.typeNameLabel).add(className);
                 }
    -            LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,
    -                    LinkInfoImpl.Kind.CLASS_SIGNATURE, typeElement);
    +            HtmlLinkInfo linkInfo = new HtmlLinkInfo(configuration,
    +                    HtmlLinkInfo.Kind.CLASS_SIGNATURE, typeElement);
                 //Let's not link to ourselves in the signature.
                 linkInfo.linkToSelf = false;
                 nameSpan.add(classWriter.getTypeParameterLinks(linkInfo));
    @@ -115,8 +140,8 @@ public Content toContent() {
                         if (superclass != null) {
                             content.add(DocletConstants.NL);
                             extendsImplements.add("extends ");
    -                        Content link = classWriter.getLink(new LinkInfoImpl(configuration,
    -                                LinkInfoImpl.Kind.CLASS_SIGNATURE_PARENT_NAME,
    +                        Content link = classWriter.getLink(new HtmlLinkInfo(configuration,
    +                                HtmlLinkInfo.Kind.CLASS_SIGNATURE_PARENT_NAME,
                                     superclass));
                             extendsImplements.add(link);
                         }
    @@ -136,8 +161,8 @@ public Content toContent() {
                             } else {
                                 extendsImplements.add(", ");
                             }
    -                        Content link = classWriter.getLink(new LinkInfoImpl(configuration,
    -                                LinkInfoImpl.Kind.CLASS_SIGNATURE_PARENT_NAME,
    +                        Content link = classWriter.getLink(new HtmlLinkInfo(configuration,
    +                                HtmlLinkInfo.Kind.CLASS_SIGNATURE_PARENT_NAME,
                                     type));
                             extendsImplements.add(link);
                         }
    @@ -166,8 +191,8 @@ public Content toContent() {
                         } else {
                             permitsSpan.add(", ");
                         }
    -                    Content link = classWriter.getLink(new LinkInfoImpl(configuration,
    -                            LinkInfoImpl.Kind.PERMITTED_SUBCLASSES,
    +                    Content link = classWriter.getLink(new HtmlLinkInfo(configuration,
    +                            HtmlLinkInfo.Kind.PERMITTED_SUBCLASSES,
                                 type));
                         permitsSpan.add(link);
                     }
    @@ -190,7 +215,7 @@ private Content getRecordComponents() {
                     content.add(sep);
                     classWriter.getAnnotations(e.getAnnotationMirrors(), false)
                             .forEach(a -> { content.add(a).add(" "); });
    -                Content link = classWriter.getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.RECORD_COMPONENT,
    +                Content link = classWriter.getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.RECORD_COMPONENT,
                             e.asType()));
                     content.add(link);
                     content.add(Entity.NO_BREAK_SPACE);
    @@ -265,7 +290,7 @@ MemberSignature setReturnType(Content returnType) {
              * @return this instance
              */
             MemberSignature setType(TypeMirror type) {
    -            this.returnType = memberWriter.writer.getLink(new LinkInfoImpl(memberWriter.configuration, LinkInfoImpl.Kind.MEMBER, type));
    +            this.returnType = memberWriter.writer.getLink(new HtmlLinkInfo(memberWriter.configuration, HtmlLinkInfo.Kind.MEMBER, type));
                 return this;
             }
     
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java
    index ead520440d1..5cf33b429ca 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -319,14 +319,14 @@ public Content throwsTagOutput(Element element, ThrowsTree throwsTag, TypeMirror
             Element exception = ch.getException(throwsTag);
             Content excName;
             if (substituteType != null) {
    -           excName = htmlWriter.getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER,
    +           excName = htmlWriter.getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.MEMBER,
                        substituteType));
             } else if (exception == null) {
                 excName = new RawHtml(ch.getExceptionName(throwsTag).toString());
             } else if (exception.asType() == null) {
                 excName = new RawHtml(utils.getFullyQualifiedName(exception));
             } else {
    -            LinkInfoImpl link = new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER,
    +            HtmlLinkInfo link = new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.MEMBER,
                                                      exception.asType());
                 link.excludeTypeBounds = true;
                 excName = htmlWriter.getLink(link);
    @@ -345,14 +345,14 @@ public Content throwsTagOutput(Element element, ThrowsTree throwsTag, TypeMirror
         @Override
         public Content throwsTagOutput(TypeMirror throwsType) {
             HtmlTree result = HtmlTree.DD(HtmlTree.CODE(htmlWriter.getLink(
    -                new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER, throwsType))));
    +                new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.MEMBER, throwsType))));
             return result;
         }
     
         @Override
         public Content valueTagOutput(VariableElement field, String constantVal, boolean includeLink) {
             return includeLink
    -                ? htmlWriter.getDocLink(LinkInfoImpl.Kind.VALUE_TAG, field, constantVal, false)
    +                ? htmlWriter.getDocLink(HtmlLinkInfo.Kind.VALUE_TAG, field, constantVal)
                     : new StringContent(constantVal);
         }
     
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Links.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Links.java
    index 354f37b819c..52b0000b75c 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Links.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Links.java
    @@ -85,7 +85,7 @@ public Content createLink(HtmlId id, Content label, String title) {
          * @return a content tree for the link
          */
         public Content createLink(DocPath path, String label) {
    -        return createLink(path, new StringContent(label), false, "");
    +        return createLink(path, new StringContent(label), null, "");
         }
     
         /**
    @@ -101,17 +101,16 @@ public Content createLink(DocPath path, Content label) {
     
         /**
          * Creates a link of the form {@code label}.
    -     * If {@code strong} is set, the label will be wrapped in
    -     *      {@code ...}.
    +     * If {@code style} is not null, it will be added as {@code class="style"} to the link.
          *
          * @param path      the path for the link
          * @param label     the content for the link
    -     * @param strong    whether to wrap the {@code label} in a SPAN element
    +     * @param style     the style for the link, or null
          * @param title     the title for the link
          * @return a content tree for the link
          */
    -    public Content createLink(DocPath path, Content label, boolean strong, String title) {
    -        return createLink(new DocLink(path), label, strong, title);
    +    public Content createLink(DocPath path, Content label, HtmlStyle style, String title) {
    +        return createLink(new DocLink(path), label, style, title);
         }
     
         /**
    @@ -155,44 +154,42 @@ public Content createLink(DocLink link, Content label, String title) {
     
         /**
          * Creates a link of the form {@code label}.
    -     * If {@code strong} is set, the label will be wrapped in
    -     *      {@code ...}.
    +     * If {@code style} is not null, it will be added as {@code class="style"} to the link.
          *
          * @param link      the details for the link
          * @param label     the content for the link
    -     * @param strong    whether to wrap the {@code label} in a SPAN element
    +     * @param style     the style for the link, or null
          * @param title     the title for the link
          * @return a content tree for the link
          */
    -    public Content createLink(DocLink link, Content label, boolean strong,
    +    public Content createLink(DocLink link, Content label, HtmlStyle style,
                                   String title) {
    -        return createLink(link, label, strong, title, false);
    +        return createLink(link, label, style, title, false);
         }
     
         /**
          * Creates a link of the form {@code label}.
    -     * If {@code strong} is set, the label will be wrapped in
    -     *      {@code ...}.
    +     * If {@code style} is not null, it will be added as {@code class="style"} to the link.
          *
          * @param link       the details for the link
          * @param label      the content for the link
    -     * @param strong     whether to wrap the {@code label} in a SPAN element
    +     * @param style      the style for the link, or null
          * @param title      the title for the link
          * @param isExternal is the link external to the generated documentation
          * @return a content tree for the link
          */
    -    public Content createLink(DocLink link, Content label, boolean strong,
    +    public Content createLink(DocLink link, Content label, HtmlStyle style,
                                   String title, boolean isExternal) {
    -        Content body = label;
    -        if (strong) {
    -            body = HtmlTree.SPAN(HtmlStyle.typeNameLink, body);
    +        HtmlTree l = HtmlTree.A(link.relativizeAgainst(file).toString(), label);
    +        if (style != null) {
    +            l.setStyle(style);
             }
    -        HtmlTree l = HtmlTree.A(link.relativizeAgainst(file).toString(), body);
             if (title != null && title.length() != 0) {
                 l.put(HtmlAttr.TITLE, title);
             }
             if (isExternal) {
    -            l.setStyle(HtmlStyle.externalLink);
    +            // Use addStyle as external links might have an explicit style set above as well.
    +            l.addStyle(HtmlStyle.externalLink);
             }
             return l;
         }
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java
    index f65462eb92d..3ccd2632da7 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java
    @@ -106,16 +106,6 @@ public abstract class BaseConfiguration {
          */
         public TagletManager tagletManager;
     
    -    /**
    -     * The path to the builder XML input file.
    -     */
    -    public String builderXMLPath;
    -
    -    /**
    -     * The default path to the builder XML.
    -     */
    -    public static final String DEFAULT_BUILDER_XML = "resources/doclet.xml";
    -
         /**
          * The meta tag keywords instance.
          */
    @@ -606,18 +596,6 @@ public boolean isGeneratedDoc(TypeElement te) {
          */
         public abstract WriterFactory getWriterFactory();
     
    -    /**
    -     * Return the input stream to the builder XML.
    -     *
    -     * @return the input steam to the builder XML.
    -     * @throws DocFileIOException when the given XML file cannot be found or opened.
    -     */
    -    public InputStream getBuilderXML() throws DocFileIOException {
    -        return builderXMLPath == null ?
    -                BaseConfiguration.class.getResourceAsStream(DEFAULT_BUILDER_XML) :
    -                DocFile.createFileForInput(this, builderXMLPath).openInputStream();
    -    }
    -
         /**
          * Return the Locale for this document.
          *
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java
    index 33ed2e9798a..60afb6859e4 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WorkArounds.java
    @@ -198,6 +198,18 @@ public TypeElement searchClass(TypeElement klass, String className) {
             return elementUtils.getTypeElement(className);
         }
     
    +
    +    // TODO: The following should be replaced by a new method such as Elements.isAutomaticModule
    +    // see JDK-8261625
    +    public boolean isAutomaticModule(ModuleElement me) {
    +        if (me == null) {
    +            return false;
    +        } else {
    +            ModuleSymbol msym = (ModuleSymbol) me;
    +            return (msym.flags() & Flags.AUTOMATIC_MODULE) != 0;
    +        }
    +    }
    +
         // TODO:  need to re-implement this using j.l.m. correctly!, this has
         //        implications on testInterface, the note here is that javac's supertype
         //        does the right thing returning Parameters in scope.
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java
    index 2c6641d9a6e..a3457787f87 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -409,6 +409,9 @@ private void buildInheritedSummary(MemberSummaryWriter writer,
                 if (inheritedClass == typeElement) {
                     continue;
                 }
    +            if (utils.hasHiddenTag(inheritedClass)) {
    +                continue;
    +            }
     
                 List members = inheritedMembersFromMap.stream()
                         .filter(e -> utils.getEnclosingTypeElement(e) == inheritedClass)
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/SerializedFormBuilder.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/SerializedFormBuilder.java
    index cabc48511ff..0ccb1f8f4a3 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/SerializedFormBuilder.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/SerializedFormBuilder.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -552,10 +552,8 @@ private static boolean serialClassInclude(Utils utils, TypeElement te) {
             if (utils.isSerializable(te)) {
                 if (utils.hasDocCommentTree(te) && !utils.getSerialTrees(te).isEmpty()) {
                     return serialDocInclude(utils, te);
    -            } else if (utils.isPublic(te) || utils.isProtected(te)) {
    -                return true;
                 } else {
    -                return false;
    +                return utils.isPublic(te) || utils.isProtected(te);
                 }
             }
             return false;
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/releases/element-list-10.txt b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/releases/element-list-10.txt
    index 16518f6620e..57462b7ebca 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/releases/element-list-10.txt
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/releases/element-list-10.txt
    @@ -1,4 +1,6 @@
    +module:java.activation
     javax.activation
    +module:java.base
     java.io
     java.lang
     java.lang.annotation
    @@ -50,22 +52,24 @@ javax.security.auth.login
     javax.security.auth.spi
     javax.security.auth.x500
     javax.security.cert
    +module:java.compiler
     javax.annotation.processing
     javax.lang.model
     javax.lang.model.element
     javax.lang.model.type
     javax.lang.model.util
     javax.tools
    +module:java.corba
     javax.activity
     javax.rmi
     javax.rmi.CORBA
     org.omg.CORBA
    -org.omg.CORBA_2_3
    -org.omg.CORBA_2_3.portable
     org.omg.CORBA.DynAnyPackage
     org.omg.CORBA.ORBPackage
    -org.omg.CORBA.portable
     org.omg.CORBA.TypeCodePackage
    +org.omg.CORBA.portable
    +org.omg.CORBA_2_3
    +org.omg.CORBA_2_3.portable
     org.omg.CosNaming
     org.omg.CosNaming.NamingContextExtPackage
     org.omg.CosNaming.NamingContextPackage
    @@ -83,11 +87,13 @@ org.omg.PortableServer
     org.omg.PortableServer.CurrentPackage
     org.omg.PortableServer.POAManagerPackage
     org.omg.PortableServer.POAPackage
    -org.omg.PortableServer.portable
     org.omg.PortableServer.ServantLocatorPackage
    +org.omg.PortableServer.portable
     org.omg.SendingContext
     org.omg.stub.java.rmi
    +module:java.datatransfer
     java.awt.datatransfer
    +module:java.desktop
     java.applet
     java.awt
     java.awt.color
    @@ -138,9 +144,13 @@ javax.swing.text.html.parser
     javax.swing.text.rtf
     javax.swing.tree
     javax.swing.undo
    +module:java.instrument
     java.lang.instrument
    +module:java.jnlp
     javax.jnlp
    +module:java.logging
     java.util.logging
    +module:java.management
     java.lang.management
     javax.management
     javax.management.loading
    @@ -150,31 +160,43 @@ javax.management.openmbean
     javax.management.relation
     javax.management.remote
     javax.management.timer
    +module:java.management.rmi
     javax.management.remote.rmi
    +module:java.naming
     javax.naming
     javax.naming.directory
     javax.naming.event
     javax.naming.ldap
     javax.naming.spi
    +module:java.prefs
     java.util.prefs
    +module:java.rmi
     java.rmi
     java.rmi.activation
     java.rmi.dgc
     java.rmi.registry
     java.rmi.server
     javax.rmi.ssl
    +module:java.scripting
     javax.script
    +module:java.security.jgss
     javax.security.auth.kerberos
     org.ietf.jgss
    +module:java.security.sasl
     javax.security.sasl
    +module:java.smartcardio
     javax.smartcardio
    +module:java.sql
     java.sql
     javax.sql
     javax.transaction.xa
    +module:java.sql.rowset
     javax.sql.rowset
     javax.sql.rowset.serial
     javax.sql.rowset.spi
    +module:java.transaction
     javax.transaction
    +module:java.xml
     javax.xml
     javax.xml.catalog
     javax.xml.datatype
    @@ -200,18 +222,21 @@ org.w3c.dom.views
     org.xml.sax
     org.xml.sax.ext
     org.xml.sax.helpers
    +module:java.xml.bind
     javax.xml.bind
     javax.xml.bind.annotation
     javax.xml.bind.annotation.adapters
     javax.xml.bind.attachment
     javax.xml.bind.helpers
     javax.xml.bind.util
    +module:java.xml.crypto
     javax.xml.crypto
     javax.xml.crypto.dom
     javax.xml.crypto.dsig
     javax.xml.crypto.dsig.dom
     javax.xml.crypto.dsig.keyinfo
     javax.xml.crypto.dsig.spec
    +module:java.xml.ws
     javax.jws
     javax.jws.soap
     javax.xml.soap
    @@ -223,7 +248,9 @@ javax.xml.ws.soap
     javax.xml.ws.spi
     javax.xml.ws.spi.http
     javax.xml.ws.wsaddressing
    +module:java.xml.ws.annotation
     javax.annotation
    +module:javafx.base
     javafx.beans
     javafx.beans.binding
     javafx.beans.property
    @@ -234,11 +261,14 @@ javafx.collections.transformation
     javafx.event
     javafx.util
     javafx.util.converter
    +module:javafx.controls
     javafx.scene.chart
     javafx.scene.control
     javafx.scene.control.cell
     javafx.scene.control.skin
    +module:javafx.fxml
     javafx.fxml
    +module:javafx.graphics
     javafx.animation
     javafx.application
     javafx.concurrent
    @@ -257,57 +287,84 @@ javafx.scene.shape
     javafx.scene.text
     javafx.scene.transform
     javafx.stage
    +module:javafx.media
     javafx.scene.media
    +module:javafx.swing
     javafx.embed.swing
    +module:javafx.web
     javafx.scene.web
    +module:jdk.accessibility
     com.sun.java.accessibility.util
    +module:jdk.attach
     com.sun.tools.attach
     com.sun.tools.attach.spi
    +module:jdk.compiler
     com.sun.source.doctree
     com.sun.source.tree
     com.sun.source.util
     com.sun.tools.javac
    +module:jdk.dynalink
     jdk.dynalink
     jdk.dynalink.beans
     jdk.dynalink.linker
     jdk.dynalink.linker.support
     jdk.dynalink.support
    +module:jdk.httpserver
     com.sun.net.httpserver
     com.sun.net.httpserver.spi
    +module:jdk.incubator.httpclient
     jdk.incubator.http
    +module:jdk.jartool
     com.sun.jarsigner
     jdk.security.jarsigner
    +module:jdk.javadoc
     com.sun.javadoc
     com.sun.tools.javadoc
     jdk.javadoc.doclet
    +module:jdk.jconsole
     com.sun.tools.jconsole
    +module:jdk.jdi
     com.sun.jdi
     com.sun.jdi.connect
     com.sun.jdi.connect.spi
     com.sun.jdi.event
     com.sun.jdi.request
    +module:jdk.jfr
     jdk.jfr
     jdk.jfr.consumer
    +module:jdk.jshell
     jdk.jshell
     jdk.jshell.execution
     jdk.jshell.spi
     jdk.jshell.tool
    +module:jdk.jsobject
     netscape.javascript
    +module:jdk.management
     com.sun.management
    +module:jdk.management.cmm
     jdk.management.cmm
    +module:jdk.management.jfr
     jdk.management.jfr
    +module:jdk.management.resource
     jdk.management.resource
    +module:jdk.net
     jdk.net
    +module:jdk.packager.services
     jdk.packager.services
     jdk.packager.services.singleton
    +module:jdk.scripting.nashorn
     jdk.nashorn.api.scripting
     jdk.nashorn.api.tree
    +module:jdk.sctp
     com.sun.nio.sctp
    +module:jdk.security.auth
     com.sun.security.auth
     com.sun.security.auth.callback
     com.sun.security.auth.login
     com.sun.security.auth.module
    +module:jdk.security.jgss
     com.sun.security.jgss
    +module:jdk.xml.dom
     org.w3c.dom.css
     org.w3c.dom.html
     org.w3c.dom.stylesheets
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/releases/package-list-9.txt b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/releases/element-list-9.txt
    similarity index 83%
    rename from src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/releases/package-list-9.txt
    rename to src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/releases/element-list-9.txt
    index 24c17a899bb..69f4efa95a7 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/releases/package-list-9.txt
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/releases/element-list-9.txt
    @@ -1,52 +1,10 @@
    -com.sun.jarsigner
    -com.sun.java.accessibility.util
    -com.sun.javadoc
    -com.sun.jdi
    -com.sun.jdi.connect
    -com.sun.jdi.connect.spi
    -com.sun.jdi.event
    -com.sun.jdi.request
    -com.sun.management
    -com.sun.net.httpserver
    -com.sun.net.httpserver.spi
    -com.sun.nio.sctp
    -com.sun.security.auth
    -com.sun.security.auth.callback
    -com.sun.security.auth.login
    -com.sun.security.auth.module
    -com.sun.security.jgss
    -com.sun.source.doctree
    -com.sun.source.tree
    -com.sun.source.util
    -com.sun.tools.attach
    -com.sun.tools.attach.spi
    -com.sun.tools.doclets
    -com.sun.tools.doclets.standard
    -com.sun.tools.javac
    -com.sun.tools.javadoc
    -com.sun.tools.jconsole
    -java.applet
    -java.awt
    -java.awt.color
    -java.awt.datatransfer
    -java.awt.desktop
    -java.awt.dnd
    -java.awt.event
    -java.awt.font
    -java.awt.geom
    -java.awt.im
    -java.awt.im.spi
    -java.awt.image
    -java.awt.image.renderable
    -java.awt.print
    -java.beans
    -java.beans.beancontext
    +module:java.activation
    +javax.activation
    +module:java.base
     java.io
     java.lang
     java.lang.annotation
    -java.lang.instrument
     java.lang.invoke
    -java.lang.management
     java.lang.module
     java.lang.ref
     java.lang.reflect
    @@ -61,17 +19,11 @@ java.nio.charset.spi
     java.nio.file
     java.nio.file.attribute
     java.nio.file.spi
    -java.rmi
    -java.rmi.activation
    -java.rmi.dgc
    -java.rmi.registry
    -java.rmi.server
     java.security
     java.security.acl
     java.security.cert
     java.security.interfaces
     java.security.spec
    -java.sql
     java.text
     java.text.spi
     java.time
    @@ -85,56 +37,79 @@ java.util.concurrent.atomic
     java.util.concurrent.locks
     java.util.function
     java.util.jar
    -java.util.logging
    -java.util.prefs
     java.util.regex
     java.util.spi
     java.util.stream
     java.util.zip
    -javafx.animation
    -javafx.application
    -javafx.beans
    -javafx.beans.binding
    -javafx.beans.property
    -javafx.beans.property.adapter
    -javafx.beans.value
    -javafx.collections
    -javafx.collections.transformation
    -javafx.concurrent
    -javafx.css
    -javafx.css.converter
    -javafx.embed.swing
    -javafx.event
    -javafx.fxml
    -javafx.geometry
    -javafx.print
    -javafx.scene
    -javafx.scene.canvas
    -javafx.scene.chart
    -javafx.scene.control
    -javafx.scene.control.cell
    -javafx.scene.control.skin
    -javafx.scene.effect
    -javafx.scene.image
    -javafx.scene.input
    -javafx.scene.layout
    -javafx.scene.media
    -javafx.scene.paint
    -javafx.scene.shape
    -javafx.scene.text
    -javafx.scene.transform
    -javafx.scene.web
    -javafx.stage
    -javafx.util
    -javafx.util.converter
    -javax.accessibility
    -javax.activation
    -javax.activity
    -javax.annotation
    -javax.annotation.processing
     javax.crypto
     javax.crypto.interfaces
     javax.crypto.spec
    +javax.net
    +javax.net.ssl
    +javax.security.auth
    +javax.security.auth.callback
    +javax.security.auth.login
    +javax.security.auth.spi
    +javax.security.auth.x500
    +javax.security.cert
    +module:java.compiler
    +javax.annotation.processing
    +javax.lang.model
    +javax.lang.model.element
    +javax.lang.model.type
    +javax.lang.model.util
    +javax.tools
    +module:java.corba
    +javax.activity
    +javax.rmi
    +javax.rmi.CORBA
    +org.omg.CORBA
    +org.omg.CORBA.DynAnyPackage
    +org.omg.CORBA.ORBPackage
    +org.omg.CORBA.TypeCodePackage
    +org.omg.CORBA.portable
    +org.omg.CORBA_2_3
    +org.omg.CORBA_2_3.portable
    +org.omg.CosNaming
    +org.omg.CosNaming.NamingContextExtPackage
    +org.omg.CosNaming.NamingContextPackage
    +org.omg.Dynamic
    +org.omg.DynamicAny
    +org.omg.DynamicAny.DynAnyFactoryPackage
    +org.omg.DynamicAny.DynAnyPackage
    +org.omg.IOP
    +org.omg.IOP.CodecFactoryPackage
    +org.omg.IOP.CodecPackage
    +org.omg.Messaging
    +org.omg.PortableInterceptor
    +org.omg.PortableInterceptor.ORBInitInfoPackage
    +org.omg.PortableServer
    +org.omg.PortableServer.CurrentPackage
    +org.omg.PortableServer.POAManagerPackage
    +org.omg.PortableServer.POAPackage
    +org.omg.PortableServer.ServantLocatorPackage
    +org.omg.PortableServer.portable
    +org.omg.SendingContext
    +org.omg.stub.java.rmi
    +module:java.datatransfer
    +java.awt.datatransfer
    +module:java.desktop
    +java.applet
    +java.awt
    +java.awt.color
    +java.awt.desktop
    +java.awt.dnd
    +java.awt.event
    +java.awt.font
    +java.awt.geom
    +java.awt.im
    +java.awt.im.spi
    +java.awt.image
    +java.awt.image.renderable
    +java.awt.print
    +java.beans
    +java.beans.beancontext
    +javax.accessibility
     javax.imageio
     javax.imageio.event
     javax.imageio.metadata
    @@ -143,54 +118,14 @@ javax.imageio.plugins.jpeg
     javax.imageio.plugins.tiff
     javax.imageio.spi
     javax.imageio.stream
    -javax.jnlp
    -javax.jws
    -javax.jws.soap
    -javax.lang.model
    -javax.lang.model.element
    -javax.lang.model.type
    -javax.lang.model.util
    -javax.management
    -javax.management.loading
    -javax.management.modelmbean
    -javax.management.monitor
    -javax.management.openmbean
    -javax.management.relation
    -javax.management.remote
    -javax.management.remote.rmi
    -javax.management.timer
    -javax.naming
    -javax.naming.directory
    -javax.naming.event
    -javax.naming.ldap
    -javax.naming.spi
    -javax.net
    -javax.net.ssl
     javax.print
     javax.print.attribute
     javax.print.attribute.standard
     javax.print.event
    -javax.rmi
    -javax.rmi.CORBA
    -javax.rmi.ssl
    -javax.script
    -javax.security.auth
    -javax.security.auth.callback
    -javax.security.auth.kerberos
    -javax.security.auth.login
    -javax.security.auth.spi
    -javax.security.auth.x500
    -javax.security.cert
    -javax.security.sasl
    -javax.smartcardio
     javax.sound.midi
     javax.sound.midi.spi
     javax.sound.sampled
     javax.sound.sampled.spi
    -javax.sql
    -javax.sql.rowset
    -javax.sql.rowset.serial
    -javax.sql.rowset.spi
     javax.swing
     javax.swing.border
     javax.swing.colorchooser
    @@ -209,27 +144,64 @@ javax.swing.text.html.parser
     javax.swing.text.rtf
     javax.swing.tree
     javax.swing.undo
    -javax.tools
    -javax.transaction
    +module:java.instrument
    +java.lang.instrument
    +module:java.jnlp
    +javax.jnlp
    +module:java.logging
    +java.util.logging
    +module:java.management
    +java.lang.management
    +javax.management
    +javax.management.loading
    +javax.management.modelmbean
    +javax.management.monitor
    +javax.management.openmbean
    +javax.management.relation
    +javax.management.remote
    +javax.management.timer
    +module:java.management.rmi
    +javax.management.remote.rmi
    +module:java.naming
    +javax.naming
    +javax.naming.directory
    +javax.naming.event
    +javax.naming.ldap
    +javax.naming.spi
    +module:java.prefs
    +java.util.prefs
    +module:java.rmi
    +java.rmi
    +java.rmi.activation
    +java.rmi.dgc
    +java.rmi.registry
    +java.rmi.server
    +javax.rmi.ssl
    +module:java.scripting
    +javax.script
    +module:java.security.jgss
    +javax.security.auth.kerberos
    +org.ietf.jgss
    +module:java.security.sasl
    +javax.security.sasl
    +module:java.smartcardio
    +javax.smartcardio
    +module:java.sql
    +java.sql
    +javax.sql
     javax.transaction.xa
    +module:java.sql.rowset
    +javax.sql.rowset
    +javax.sql.rowset.serial
    +javax.sql.rowset.spi
    +module:java.transaction
    +javax.transaction
    +module:java.xml
     javax.xml
    -javax.xml.bind
    -javax.xml.bind.annotation
    -javax.xml.bind.annotation.adapters
    -javax.xml.bind.attachment
    -javax.xml.bind.helpers
    -javax.xml.bind.util
     javax.xml.catalog
    -javax.xml.crypto
    -javax.xml.crypto.dom
    -javax.xml.crypto.dsig
    -javax.xml.crypto.dsig.dom
    -javax.xml.crypto.dsig.keyinfo
    -javax.xml.crypto.dsig.spec
     javax.xml.datatype
     javax.xml.namespace
     javax.xml.parsers
    -javax.xml.soap
     javax.xml.stream
     javax.xml.stream.events
     javax.xml.stream.util
    @@ -239,6 +211,35 @@ javax.xml.transform.sax
     javax.xml.transform.stax
     javax.xml.transform.stream
     javax.xml.validation
    +javax.xml.xpath
    +org.w3c.dom
    +org.w3c.dom.bootstrap
    +org.w3c.dom.events
    +org.w3c.dom.ls
    +org.w3c.dom.ranges
    +org.w3c.dom.traversal
    +org.w3c.dom.views
    +org.xml.sax
    +org.xml.sax.ext
    +org.xml.sax.helpers
    +module:java.xml.bind
    +javax.xml.bind
    +javax.xml.bind.annotation
    +javax.xml.bind.annotation.adapters
    +javax.xml.bind.attachment
    +javax.xml.bind.helpers
    +javax.xml.bind.util
    +module:java.xml.crypto
    +javax.xml.crypto
    +javax.xml.crypto.dom
    +javax.xml.crypto.dsig
    +javax.xml.crypto.dsig.dom
    +javax.xml.crypto.dsig.keyinfo
    +javax.xml.crypto.dsig.spec
    +module:java.xml.ws
    +javax.jws
    +javax.jws.soap
    +javax.xml.soap
     javax.xml.ws
     javax.xml.ws.handler
     javax.xml.ws.handler.soap
    @@ -247,69 +248,125 @@ javax.xml.ws.soap
     javax.xml.ws.spi
     javax.xml.ws.spi.http
     javax.xml.ws.wsaddressing
    -javax.xml.xpath
    +module:java.xml.ws.annotation
    +javax.annotation
    +module:javafx.base
    +javafx.beans
    +javafx.beans.binding
    +javafx.beans.property
    +javafx.beans.property.adapter
    +javafx.beans.value
    +javafx.collections
    +javafx.collections.transformation
    +javafx.event
    +javafx.util
    +javafx.util.converter
    +module:javafx.controls
    +javafx.scene.chart
    +javafx.scene.control
    +javafx.scene.control.cell
    +javafx.scene.control.skin
    +module:javafx.fxml
    +javafx.fxml
    +module:javafx.graphics
    +javafx.animation
    +javafx.application
    +javafx.concurrent
    +javafx.css
    +javafx.css.converter
    +javafx.geometry
    +javafx.print
    +javafx.scene
    +javafx.scene.canvas
    +javafx.scene.effect
    +javafx.scene.image
    +javafx.scene.input
    +javafx.scene.layout
    +javafx.scene.paint
    +javafx.scene.shape
    +javafx.scene.text
    +javafx.scene.transform
    +javafx.stage
    +module:javafx.media
    +javafx.scene.media
    +module:javafx.swing
    +javafx.embed.swing
    +module:javafx.web
    +javafx.scene.web
    +module:jdk.accessibility
    +com.sun.java.accessibility.util
    +module:jdk.attach
    +com.sun.tools.attach
    +com.sun.tools.attach.spi
    +module:jdk.compiler
    +com.sun.source.doctree
    +com.sun.source.tree
    +com.sun.source.util
    +com.sun.tools.javac
    +module:jdk.dynalink
     jdk.dynalink
     jdk.dynalink.beans
     jdk.dynalink.linker
     jdk.dynalink.linker.support
     jdk.dynalink.support
    +module:jdk.httpserver
    +com.sun.net.httpserver
    +com.sun.net.httpserver.spi
    +module:jdk.incubator.httpclient
     jdk.incubator.http
    +module:jdk.jartool
    +com.sun.jarsigner
    +jdk.security.jarsigner
    +module:jdk.javadoc
    +com.sun.javadoc
    +com.sun.tools.doclets
    +com.sun.tools.doclets.standard
    +com.sun.tools.javadoc
     jdk.javadoc.doclet
    +module:jdk.jconsole
    +com.sun.tools.jconsole
    +module:jdk.jdi
    +com.sun.jdi
    +com.sun.jdi.connect
    +com.sun.jdi.connect.spi
    +com.sun.jdi.event
    +com.sun.jdi.request
    +module:jdk.jfr
     jdk.jfr
     jdk.jfr.consumer
    +module:jdk.jshell
     jdk.jshell
     jdk.jshell.execution
     jdk.jshell.spi
     jdk.jshell.tool
    +module:jdk.jsobject
    +netscape.javascript
    +module:jdk.management
    +com.sun.management
    +module:jdk.management.cmm
     jdk.management.cmm
    +module:jdk.management.jfr
     jdk.management.jfr
    +module:jdk.management.resource
     jdk.management.resource
    -jdk.nashorn.api.scripting
    -jdk.nashorn.api.tree
    +module:jdk.net
     jdk.net
    +module:jdk.packager.services
     jdk.packager.services
    -jdk.security.jarsigner
    -netscape.javascript
    -org.ietf.jgss
    -org.omg.CORBA
    -org.omg.CORBA_2_3
    -org.omg.CORBA_2_3.portable
    -org.omg.CORBA.DynAnyPackage
    -org.omg.CORBA.ORBPackage
    -org.omg.CORBA.portable
    -org.omg.CORBA.TypeCodePackage
    -org.omg.CosNaming
    -org.omg.CosNaming.NamingContextExtPackage
    -org.omg.CosNaming.NamingContextPackage
    -org.omg.Dynamic
    -org.omg.DynamicAny
    -org.omg.DynamicAny.DynAnyFactoryPackage
    -org.omg.DynamicAny.DynAnyPackage
    -org.omg.IOP
    -org.omg.IOP.CodecFactoryPackage
    -org.omg.IOP.CodecPackage
    -org.omg.Messaging
    -org.omg.PortableInterceptor
    -org.omg.PortableInterceptor.ORBInitInfoPackage
    -org.omg.PortableServer
    -org.omg.PortableServer.CurrentPackage
    -org.omg.PortableServer.POAManagerPackage
    -org.omg.PortableServer.POAPackage
    -org.omg.PortableServer.portable
    -org.omg.PortableServer.ServantLocatorPackage
    -org.omg.SendingContext
    -org.omg.stub.java.rmi
    -org.w3c.dom
    -org.w3c.dom.bootstrap
    +module:jdk.scripting.nashorn
    +jdk.nashorn.api.scripting
    +jdk.nashorn.api.tree
    +module:jdk.sctp
    +com.sun.nio.sctp
    +module:jdk.security.auth
    +com.sun.security.auth
    +com.sun.security.auth.callback
    +com.sun.security.auth.login
    +com.sun.security.auth.module
    +module:jdk.security.jgss
    +com.sun.security.jgss
    +module:jdk.xml.dom
     org.w3c.dom.css
    -org.w3c.dom.events
     org.w3c.dom.html
    -org.w3c.dom.ls
    -org.w3c.dom.ranges
     org.w3c.dom.stylesheets
    -org.w3c.dom.traversal
    -org.w3c.dom.views
     org.w3c.dom.xpath
    -org.xml.sax
    -org.xml.sax.ext
    -org.xml.sax.helpers
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java
    index 19b1e8483d8..1b6607e3dbe 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Extern.java
    @@ -47,8 +47,6 @@
     import javax.tools.Diagnostic.Kind;
     import javax.tools.DocumentationTool;
     
    -import com.sun.tools.javac.code.Flags;
    -import com.sun.tools.javac.code.Symbol.ModuleSymbol;
     import jdk.javadoc.doclet.Reporter;
     import jdk.javadoc.internal.doclets.toolkit.AbstractDoclet;
     import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
    @@ -262,8 +260,8 @@ public void checkPlatformLinks(String linkPlatformProperties, Reporter reporter)
                 if (elementListUrl == null) {
                     reporter.print(Kind.WARNING, resources.getText("doclet.Resource_error", elementListPath.getPath()));
                 } else {
    -                try {
    -                    readListFromURL(docUrl, elementListUrl);
    +                try (InputStream in = open(elementListUrl)) {
    +                    readElementList(in, docUrl, false, versionNumber);
                     } catch (IOException exc) {
                         throw new Fault(resources.getText(
                                 "doclet.Resource_error", elementListPath.getPath()), exc);
    @@ -280,7 +278,7 @@ public void checkPlatformLinks(String linkPlatformProperties, Reporter reporter)
          * @return the resource path
          */
         private DocPath getPlatformElementList(int version) {
    -        String filename = version <= 9
    +        String filename = version <= 8
                     ? "package-list-" + version + ".txt"
                     : "element-list-" + version + ".txt";
             return DocPaths.RESOURCES.resolve("releases").resolve(filename);
    @@ -426,7 +424,9 @@ private String adjustEndFileSeparator(String url) {
         private void readElementListFromURL(String urlpath, URL elemlisturlpath) throws Fault {
             try {
                 URL link = elemlisturlpath.toURI().resolve(DocPaths.ELEMENT_LIST.getPath()).toURL();
    -            readListFromURL(urlpath, link);
    +            try (InputStream in = open(link)) {
    +                readElementList(in, urlpath, false, 0);
    +            }
             } catch (URISyntaxException | MalformedURLException exc) {
                 throw new Fault(resources.getText("doclet.MalformedURL", elemlisturlpath.toString()), exc);
             } catch (IOException exc) {
    @@ -443,7 +443,9 @@ private void readElementListFromURL(String urlpath, URL elemlisturlpath) throws
         private void readPackageListFromURL(String urlpath, URL elemlisturlpath) throws Fault {
             try {
                 URL link = elemlisturlpath.toURI().resolve(DocPaths.PACKAGE_LIST.getPath()).toURL();
    -            readListFromURL(urlpath, link);
    +            try (InputStream in = open(link)) {
    +                readElementList(in, urlpath, false, 0);
    +            }
             } catch (URISyntaxException | MalformedURLException exc) {
                 throw new Fault(resources.getText("doclet.MalformedURL", elemlisturlpath.toString()), exc);
             } catch (IOException exc) {
    @@ -451,18 +453,6 @@ private void readPackageListFromURL(String urlpath, URL elemlisturlpath) throws
             }
         }
     
    -    /**
    -     * Read an element or package list from file.
    -     *
    -     * @param urlpath URL or path to the packages
    -     * @param elementlistpath URL to read "element-list" file from
    -     */
    -    private void readListFromURL(String urlpath, URL elementlistpath) throws IOException {
    -        try (InputStream in = open(elementlistpath)) {
    -            readElementList(in, urlpath, false);
    -        }
    -    }
    -
         /**
          * Read the "element-list" file which is available locally.
          *
    @@ -498,7 +488,7 @@ private void readElementList(DocFile file, String path) throws Fault, DocFileIOE
                     boolean pathIsRelative
                             = !isUrl(path)
                             && !DocFile.createFileForInput(configuration, path).isAbsolute();
    -                readElementList(file.openInputStream(), path, pathIsRelative);
    +                readElementList(file.openInputStream(), path, pathIsRelative, 0);
                 } else {
                     throw new Fault(resources.getText("doclet.File_error", file.getPath()), null);
                 }
    @@ -514,9 +504,11 @@ private void readElementList(DocFile file, String path) throws Fault, DocFileIOE
          * @param input     InputStream from the "element-list" file.
          * @param path     URL or the directory path to the elements.
          * @param relative Is path relative?
    +     * @param platformVersion The version of platform libraries the element list belongs to,
    +     *                        or {@code 0} if it does not belong to a platform libraries doc bundle.
          * @throws IOException if there is a problem reading or closing the stream
          */
    -    private void readElementList(InputStream input, String path, boolean relative)
    +    private void readElementList(InputStream input, String path, boolean relative, int platformVersion)
                              throws IOException {
             try (BufferedReader in = new BufferedReader(new InputStreamReader(input))) {
                 String elemname;
    @@ -533,12 +525,20 @@ private void readElementList(InputStream input, String path, boolean relative)
                             moduleItems.put(moduleName, item);
                         } else {
                             DocPath pkgPath = DocPath.create(elemname.replace('.', '/'));
    -                        if (moduleName != null) {
    +                        // Although being modular, JDKs 9 and 10 do not use module names in javadoc URL paths.
    +                        if (moduleName != null && platformVersion != 9 && platformVersion != 10) {
                                 elempath = elempath.resolve(DocPath.create(moduleName).resolve(pkgPath));
                             } else {
                                 elempath = elempath.resolve(pkgPath);
                             }
    -                        String actualModuleName = checkLinkCompatibility(elemname, moduleName, path, issueWarning);
    +                        String actualModuleName;
    +                        // For user provided libraries we check whether modularity matches the actual library.
    +                        // We trust modularity to be correct for platform library element lists.
    +                        if (platformVersion == 0) {
    +                            actualModuleName = checkLinkCompatibility(elemname, moduleName, path, issueWarning);
    +                        } else {
    +                            actualModuleName = moduleName == null ? DocletConstants.DEFAULT_ELEMENT_NAME : moduleName;
    +                        }
                             Item item = new Item(elemname, elempath, relative);
                             packageItems.computeIfAbsent(actualModuleName, k -> new TreeMap<>())
                                 .putIfAbsent(elemname, item); // first-one-wins semantics
    @@ -573,7 +573,7 @@ private String checkLinkCompatibility(String packageName, String moduleName, Str
                     return DocletConstants.DEFAULT_ELEMENT_NAME;
                 } else if (moduleName == null) {
                     // suppress the warning message in the case of automatic modules
    -                if (!isAutomaticModule(me) && issueWarning) {
    +                if (!configuration.workArounds.isAutomaticModule(me) && issueWarning) {
                         configuration.getReporter().print(Kind.WARNING,
                                 resources.getText("doclet.linkMismatch_ModuleLinkedtoPackage", path));
                     }
    @@ -584,16 +584,6 @@ private String checkLinkCompatibility(String packageName, String moduleName, Str
             return moduleName == null ? DocletConstants.DEFAULT_ELEMENT_NAME : moduleName;
         }
     
    -    // The following should be replaced by a new method such as Elements.isAutomaticModule
    -    private boolean isAutomaticModule(ModuleElement me) {
    -        if (me == null) {
    -            return false;
    -        } else {
    -            ModuleSymbol msym = (ModuleSymbol) me;
    -            return (msym.flags() & Flags.AUTOMATIC_MODULE) != 0;
    -        }
    -    }
    -
         public boolean isUrl (String urlCandidate) {
             try {
                 new URL(urlCandidate);
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
    index 89636e9c8e3..b6b2a5a82b9 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java
    @@ -609,7 +609,8 @@ public boolean isOrdinaryClass(TypeElement te) {
         }
     
         public boolean isUndocumentedEnclosure(TypeElement enclosingTypeElement) {
    -        return (isPackagePrivate(enclosingTypeElement) || isPrivate(enclosingTypeElement))
    +        return (isPackagePrivate(enclosingTypeElement) || isPrivate(enclosingTypeElement)
    +                    || hasHiddenTag(enclosingTypeElement))
                     && !isLinkable(enclosingTypeElement);
         }
     
    @@ -1157,10 +1158,11 @@ public boolean isDocumentedAnnotation(TypeElement annotation) {
          */
         public boolean isLinkable(TypeElement typeElem) {
             return
    -            (typeElem != null &&
    -                (isIncluded(typeElem) && configuration.isGeneratedDoc(typeElem))) ||
    +            typeElem != null &&
    +            ((isIncluded(typeElem) && configuration.isGeneratedDoc(typeElem) &&
    +                    !hasHiddenTag(typeElem)) ||
                 (configuration.extern.isExternal(typeElem) &&
    -                (isPublic(typeElem) || isProtected(typeElem)));
    +                    (isPublic(typeElem) || isProtected(typeElem))));
         }
     
         /**
    @@ -1183,7 +1185,7 @@ public boolean isLinkable(TypeElement typeElem, Element elem) {
                 return isLinkable((TypeElement) elem); // defer to existing behavior
             }
     
    -        if (isIncluded(elem)) {
    +        if (isIncluded(elem) && !hasHiddenTag(elem)) {
                 return true;
             }
     
    @@ -1553,16 +1555,17 @@ public String propertyName(ExecutableElement e) {
         }
     
         /**
    -     * Returns true if the element is included, contains @hidden tag,
    +     * Returns true if the element is included or selected, contains @hidden tag,
          * or if javafx flag is present and element contains @treatAsPrivate
          * tag.
          * @param e the queried element
          * @return true if it exists, false otherwise
          */
         public boolean hasHiddenTag(Element e) {
    -        // prevent needless tests on elements which are not included
    +        // Non-included elements may still be visible via "transclusion" from undocumented enclosures,
    +        // but we don't want to run doclint on them, possibly causing warnings or errors.
             if (!isIncluded(e)) {
    -            return false;
    +            return hasBlockTagUnchecked(e, HIDDEN);
             }
             if (options.javafx() &&
                     hasBlockTag(e, DocTree.Kind.UNKNOWN_BLOCK_TAG, "treatAsPrivate")) {
    @@ -2265,12 +2268,14 @@ protected String defaultAction(Element e, Void p) {
         }
     
         public TypeElement getEnclosingTypeElement(Element e) {
    -        if (e.getKind() == ElementKind.PACKAGE)
    +        if (isPackage(e) || isModule(e)) {
                 return null;
    +        }
             Element encl = e.getEnclosingElement();
    -        ElementKind kind = encl.getKind();
    -        if (kind == ElementKind.PACKAGE)
    +        if (isPackage(encl)) {
                 return null;
    +        }
    +        ElementKind kind = encl.getKind();
             while (!(kind.isClass() || kind.isInterface())) {
                 encl = encl.getEnclosingElement();
                 kind = encl.getKind();
    @@ -2591,7 +2596,10 @@ public void removeCommentHelper(Element element) {
         }
     
         public List getBlockTags(Element element) {
    -        DocCommentTree dcTree = getDocCommentTree(element);
    +        return getBlockTags(getDocCommentTree(element));
    +    }
    +
    +    public List getBlockTags(DocCommentTree dcTree) {
             return dcTree == null ? Collections.emptyList() : dcTree.getBlockTags();
         }
     
    @@ -2641,14 +2649,26 @@ public boolean hasBlockTag(Element element, DocTree.Kind kind) {
         public boolean hasBlockTag(Element element, DocTree.Kind kind, final String tagName) {
             if (hasDocCommentTree(element)) {
                 CommentHelper ch = getCommentHelper(element);
    -            String tname = tagName != null && tagName.startsWith("@")
    -                    ? tagName.substring(1)
    -                    : tagName;
    -            for (DocTree dt : getBlockTags(element, kind)) {
    +            for (DocTree dt : getBlockTags(ch.dcTree)) {
    +                if (dt.getKind() == kind && (tagName == null || ch.getTagName(dt).equals(tagName))) {
    +                    return true;
    +                }
    +            }
    +        }
    +        return false;
    +    }
    +
    +    /*
    +     * Tests whether an element's doc comment contains a block tag without caching it or
    +     * running doclint on it. This is done by using getDocCommentInfo(Element) to retrieve
    +     * the doc comment info.
    +     */
    +    boolean hasBlockTagUnchecked(Element element, DocTree.Kind kind) {
    +        DocCommentInfo dcInfo = getDocCommentInfo(element);
    +        if (dcInfo != null && dcInfo.dcTree != null) {
    +            for (DocTree dt : getBlockTags(dcInfo.dcTree)) {
                     if (dt.getKind() == kind) {
    -                    if (tname == null || ch.getTagName(dt).equals(tname)) {
    -                        return true;
    -                    }
    +                    return true;
                     }
                 }
             }
    @@ -2701,7 +2721,7 @@ public boolean hasDocCommentTree(Element element) {
     
         /**
          * Retrieves the doc comments for a given element.
    -     * @param element
    +     * @param element the element
          * @return DocCommentTree for the Element
          */
         public DocCommentTree getDocCommentTree0(Element element) {
    @@ -2759,7 +2779,7 @@ private DocCommentInfo getDocCommentInfo(Element element) {
     
         private DocCommentInfo getDocCommentInfo0(Element element) {
             // prevent nasty things downstream with overview element
    -        if (element.getKind() != ElementKind.OTHER) {
    +        if (!isOverviewElement(element)) {
                 TreePath path = getTreePath(element);
                 if (path != null) {
                     DocCommentTree docCommentTree = docTrees.getDocCommentTree(path);
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java
    index ea30748cf2f..0d3604b4535 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java
    @@ -126,7 +126,7 @@ public enum Kind {
         private Map propertyMap = new HashMap<>();
     
         // Keeps track of method overrides
    -    Map overriddenMethodTable
    +    Map overriddenMethodTable
                 = new LinkedHashMap<>();
     
         protected VisibleMemberTable(TypeElement typeElement, BaseConfiguration configuration,
    @@ -240,10 +240,10 @@ public List getMembers(Kind kind) {
         public ExecutableElement getOverriddenMethod(ExecutableElement e) {
             ensureInitialized();
     
    -        OverridingMethodInfo found = overriddenMethodTable.get(e);
    +        OverriddenMethodInfo found = overriddenMethodTable.get(e);
             if (found != null
                     && (found.simpleOverride || utils.isUndocumentedEnclosure(utils.getEnclosingTypeElement(e)))) {
    -            return found.overrider;
    +            return found.overridden;
             }
             return null;
         }
    @@ -256,9 +256,9 @@ public ExecutableElement getOverriddenMethod(ExecutableElement e) {
         public ExecutableElement getSimplyOverriddenMethod(ExecutableElement e) {
             ensureInitialized();
     
    -        OverridingMethodInfo found = overriddenMethodTable.get(e);
    +        OverriddenMethodInfo found = overriddenMethodTable.get(e);
             if (found != null && found.simpleOverride) {
    -            return found.overrider;
    +            return found.overridden;
             }
             return null;
         }
    @@ -475,9 +475,9 @@ private void computeVisibleMethods(LocalMemberTable lmt) {
             for (VisibleMemberTable pvmt : parents) {
                 // Merge the lineage overrides into local table
                 pvmt.overriddenMethodTable.entrySet().forEach(e -> {
    -                OverridingMethodInfo p = e.getValue();
    +                OverriddenMethodInfo p = e.getValue();
                     if (!p.simpleOverride) { // consider only real overrides
    -                    List list = overriddenByTable.computeIfAbsent(p.overrider,
    +                    List list = overriddenByTable.computeIfAbsent(p.overridden,
                                 k -> new ArrayList<>());
                         list.add(e.getKey());
                     }
    @@ -486,19 +486,19 @@ private void computeVisibleMethods(LocalMemberTable lmt) {
             }
     
             // Filter out inherited methods that:
    -        // a. cannot override (private instance members)
    +        // a. cannot be overridden (private instance members)
             // b. are overridden and should not be visible in this type
             // c. are hidden in the type being considered
    -        // see allowInheritedMethods, which performs the above actions
    +        // see allowInheritedMethod, which performs the above actions
             List list = inheritedMethods.stream()
    -                .filter(e -> allowInheritedMethods((ExecutableElement) e, overriddenByTable, lmt))
    +                .filter(e -> allowInheritedMethod((ExecutableElement) e, overriddenByTable, lmt))
                     .collect(Collectors.toList());
     
             // Filter out the local methods, that do not override or simply
             // overrides a super method, or those methods that should not
             // be visible.
             Predicate isVisible = m -> {
    -            OverridingMethodInfo p = overriddenMethodTable.getOrDefault(m, null);
    +            OverriddenMethodInfo p = overriddenMethodTable.getOrDefault(m, null);
                 return p == null || !p.simpleOverride;
             };
             List localList = lmt.getOrderedMembers(Kind.METHODS)
    @@ -529,9 +529,9 @@ boolean isEnclosureInterface(Element e) {
             return utils.isInterface(enclosing);
         }
     
    -    boolean allowInheritedMethods(ExecutableElement inheritedMethod,
    -                                  Map> inheritedOverriddenTable,
    -                                  LocalMemberTable lmt) {
    +    boolean allowInheritedMethod(ExecutableElement inheritedMethod,
    +                                 Map> overriddenByTable,
    +                                 LocalMemberTable lmt) {
             if (!isInherited(inheritedMethod))
                 return false;
     
    @@ -552,7 +552,7 @@ boolean allowInheritedMethods(ExecutableElement inheritedMethod,
             // in favor of concrete overriding methods, for instance those that have
             // API documentation and are not abstract OR default methods.
             if (inInterface) {
    -            List list = inheritedOverriddenTable.get(inheritedMethod);
    +            List list = overriddenByTable.get(inheritedMethod);
                 if (list != null) {
                     boolean found = list.stream()
                             .anyMatch(this::isEnclosureInterface);
    @@ -586,16 +586,19 @@ boolean allowInheritedMethods(ExecutableElement inheritedMethod,
                     TypeElement encl = utils.getEnclosingTypeElement(inheritedMethod);
                     if (utils.isUndocumentedEnclosure(encl)) {
                         overriddenMethodTable.computeIfAbsent(lMethod,
    -                            l -> new OverridingMethodInfo(inheritedMethod, false));
    +                            l -> new OverriddenMethodInfo(inheritedMethod, false));
                         return false;
                     }
     
                     // Even with --override-methods=summary we want to include details of
    -                // overriding method if something noteworthy has been added or changed.
    +                // overriding method if something noteworthy has been added or changed
    +                // either in the local overriding method or an in-between overriding method
    +                // (as evidenced by an entry in overriddenByTable).
                     boolean simpleOverride = utils.isSimpleOverride(lMethod)
    -                        && !overridingSignatureChanged(lMethod, inheritedMethod);
    +                        && !overridingSignatureChanged(lMethod, inheritedMethod)
    +                        && !overriddenByTable.containsKey(inheritedMethod);
                     overriddenMethodTable.computeIfAbsent(lMethod,
    -                        l -> new OverridingMethodInfo(inheritedMethod, simpleOverride));
    +                        l -> new OverriddenMethodInfo(inheritedMethod, simpleOverride));
                     return simpleOverride;
                 }
             }
    @@ -1031,21 +1034,21 @@ private boolean overridingMethodFound(ExecutableElement method) {
         }
     
         /**
    -     * A simple container to encapsulate an overriding method
    +     * A simple container to encapsulate an overridden method
          * and the type of override.
          */
    -    static class OverridingMethodInfo {
    -        final ExecutableElement overrider;
    +    static class OverriddenMethodInfo {
    +        final ExecutableElement overridden;
             final boolean simpleOverride;
     
    -        public OverridingMethodInfo(ExecutableElement overrider, boolean simpleOverride) {
    -            this.overrider = overrider;
    +        public OverriddenMethodInfo(ExecutableElement overridden, boolean simpleOverride) {
    +            this.overridden = overridden;
                 this.simpleOverride = simpleOverride;
             }
     
             @Override
             public String toString() {
    -            return "OverridingMethodInfo[" + overrider + ",simple:" + simpleOverride + "]";
    +            return "OverriddenMethodInfo[" + overridden + ",simple:" + simpleOverride + "]";
             }
         }
     }
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java
    index d2de0fd28b3..cb1b16a4f88 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkFactory.java
    @@ -35,8 +35,7 @@
     import javax.lang.model.type.TypeMirror;
     import javax.lang.model.type.TypeVariable;
     import javax.lang.model.type.WildcardType;
    -import javax.lang.model.util.SimpleTypeVisitor9;
    -import jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl;
    +import javax.lang.model.util.SimpleTypeVisitor14;
     
     import jdk.javadoc.internal.doclets.toolkit.Content;
     import jdk.javadoc.internal.doclets.toolkit.util.Utils;
    @@ -57,7 +56,7 @@ protected LinkFactory(Utils utils) {
         }
     
         /**
    -     * Return an empty instance of a content object.
    +     * Returns an empty instance of a content object.
          *
          * @return an empty instance of a content object.
          */
    @@ -71,11 +70,9 @@ protected LinkFactory(Utils utils) {
          */
         public Content getLink(LinkInfo linkInfo) {
             if (linkInfo.type != null) {
    -            SimpleTypeVisitor9 linkVisitor =
    -                    new SimpleTypeVisitor9() {
    +            SimpleTypeVisitor14 linkVisitor = new SimpleTypeVisitor14<>() {
     
    -                TypeMirror componentType = utils.getComponentType(linkInfo.type);
    -                Content link = newContent();
    +                final Content link = newContent();
     
                     // handles primitives, no types and error types
                     @Override
    @@ -109,7 +106,6 @@ public Content visitArray(ArrayType type, LinkInfo linkInfo) {
     
                     @Override
                     public Content visitWildcard(WildcardType type, LinkInfo linkInfo) {
    -                    linkInfo.isTypeBound = true;
                         link.add(getTypeAnnotationLinks(linkInfo));
                         link.add("?");
                         TypeMirror extendsBound = type.getExtendsBound();
    @@ -130,12 +126,11 @@ public Content visitWildcard(WildcardType type, LinkInfo linkInfo) {
                     @Override
                     public Content visitTypeVariable(TypeVariable type, LinkInfo linkInfo) {
                         link.add(getTypeAnnotationLinks(linkInfo));
    -                    linkInfo.isTypeBound = true;
                         TypeVariable typevariable = (utils.isArrayType(type))
    -                            ? (TypeVariable) componentType
    +                            ? (TypeVariable) utils.getComponentType(type)
                                 : type;
                         Element owner = typevariable.asElement().getEnclosingElement();
    -                    if ((!linkInfo.excludeTypeParameterLinks) && utils.isTypeElement(owner)) {
    +                    if (!linkInfo.excludeTypeParameterLinks && utils.isTypeElement(owner)) {
                             linkInfo.typeElement = (TypeElement) owner;
                             Content label = newContent();
                             label.add(utils.getTypeName(type, false));
    @@ -171,20 +166,11 @@ public Content visitTypeVariable(TypeVariable type, LinkInfo linkInfo) {
     
                     @Override
                     public Content visitDeclared(DeclaredType type, LinkInfo linkInfo) {
    -                    if (linkInfo.isTypeBound && linkInfo.excludeTypeBoundsLinks) {
    -                        // Since we are excluding type parameter links, we should not
    -                        // be linking to the type bound.
    -                        link.add(utils.getTypeName(type, false));
    +                    link.add(getTypeAnnotationLinks(linkInfo));
    +                    linkInfo.typeElement = utils.asTypeElement(type);
    +                    link.add(getClassLink(linkInfo));
    +                    if (linkInfo.includeTypeParameterLinks()) {
                             link.add(getTypeParameterLinks(linkInfo));
    -                        return link;
    -                    } else {
    -                        link = newContent();
    -                        link.add(getTypeAnnotationLinks(linkInfo));
    -                        linkInfo.typeElement = utils.asTypeElement(type);
    -                        link.add(getClassLink(linkInfo));
    -                        if (linkInfo.includeTypeAsSepLink) {
    -                            link.add(getTypeParameterLinks(linkInfo, false));
    -                        }
                         }
                         return link;
                     }
    @@ -193,8 +179,8 @@ public Content visitDeclared(DeclaredType type, LinkInfo linkInfo) {
             } else if (linkInfo.typeElement != null) {
                 Content link = newContent();
                 link.add(getClassLink(linkInfo));
    -            if (linkInfo.includeTypeAsSepLink) {
    -                link.add(getTypeParameterLinks(linkInfo, false));
    +            if (linkInfo.includeTypeParameterLinks()) {
    +                link.add(getTypeParameterLinks(linkInfo));
                 }
                 return link;
             } else {
    @@ -213,7 +199,6 @@ private void setBoundsLinkInfo(LinkInfo linkInfo, TypeMirror bound) {
          * Returns a link to the given class.
          *
          * @param linkInfo the information about the link to construct
    -     *
          * @return the link for the given class.
          */
         protected abstract Content getClassLink(LinkInfo linkInfo);
    @@ -221,22 +206,16 @@ private void setBoundsLinkInfo(LinkInfo linkInfo, TypeMirror bound) {
         /**
          * Returns links to the type parameters.
          *
    -     * @param linkInfo     the information about the link to construct
    -     * @param isClassLabel true if this is a class label, or false if it is
    -     *                     the type parameters portion of the link
    +     * @param linkInfo the information about the link to construct
          * @return the links to the type parameters
          */
    -    protected abstract Content getTypeParameterLinks(LinkInfo linkInfo, boolean isClassLabel);
    +    protected abstract Content getTypeParameterLinks(LinkInfo linkInfo);
     
         /**
    -     * Returns links to the type parameters.
    +     * Returns links to the type annotations.
          *
    -     * @param linkInfo     the information about the link to construct
    -     * @return the links to the type parameters.
    +     * @param linkInfo the information about the link to construct
    +     * @return the links to the type annotations
          */
    -    public Content getTypeParameterLinks(LinkInfo linkInfo) {
    -        return getTypeParameterLinks(linkInfo, true);
    -    }
    -
         public abstract Content getTypeAnnotationLinks(LinkInfo linkInfo);
     }
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkInfo.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkInfo.java
    index 37dee02f3b6..1907ad426d1 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkInfo.java
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/links/LinkInfo.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -64,31 +64,11 @@ public abstract class LinkInfo {
          */
         public boolean isVarArg = false;
     
    -    /**
    -     * Set this to true to indicate that you are linking to a type parameter.
    -     */
    -    public boolean isTypeBound = false;
    -
         /**
          * The label for the link.
          */
         public Content label;
     
    -    /**
    -     * True if the link should be strong.
    -     */
    -    public boolean isStrong = false;
    -
    -    /**
    -     * True if we should include the type in the link label.  False otherwise.
    -     */
    -    public boolean includeTypeInClassLinkLabel = true;
    -
    -    /**
    -     * True if we should include the type as separate link.  False otherwise.
    -     */
    -    public boolean includeTypeAsSepLink = false;
    -
         /**
          * True if we should exclude the type bounds for the type parameter.
          */
    @@ -99,11 +79,6 @@ public abstract class LinkInfo {
          */
         public boolean excludeTypeParameterLinks = false;
     
    -    /**
    -     * True if we should print the type bounds, but not link them.
    -     */
    -    public boolean excludeTypeBoundsLinks = false;
    -
         /**
          * By default, the link can be to the page it's already on.  However,
          * there are cases where we don't want this (e.g. heading of class page).
    @@ -116,14 +91,14 @@ public abstract class LinkInfo {
         public boolean skipPreview;
     
         /**
    -     * Return an empty instance of a content object.
    +     * Returns an empty instance of a content object.
          *
          * @return an empty instance of a content object.
          */
         protected abstract Content newContent();
     
         /**
    -     * Return true if this link is linkable and false if we can't link to the
    +     * Returns true if this link is linkable and false if we can't link to the
          * desired place.
          *
          * @return true if this link is linkable and false if we can't link to the
    @@ -131,6 +106,14 @@ public abstract class LinkInfo {
          */
         public abstract boolean isLinkable();
     
    +    /**
    +     * Returns true if links to declared types should include links to the
    +     * type parameters.
    +     *
    +     * @return true if type parameter links should be included
    +     */
    +    public abstract boolean includeTypeParameterLinks();
    +
         /**
          * Return the label for this class link.
          *
    @@ -157,14 +140,9 @@ public String toString() {
                     ", executableElement=" + executableElement +
                     ", type=" + type +
                     ", isVarArg=" + isVarArg +
    -                ", isTypeBound=" + isTypeBound +
                     ", label=" + label +
    -                ", isStrong=" + isStrong +
    -                ", includeTypeInClassLinkLabel=" + includeTypeInClassLinkLabel +
    -                ", includeTypeAsSepLink=" + includeTypeAsSepLink +
                     ", excludeTypeBounds=" + excludeTypeBounds +
                     ", excludeTypeParameterLinks=" + excludeTypeParameterLinks +
    -                ", excludeTypeBoundsLinks=" + excludeTypeBoundsLinks +
                     ", linkToSelf=" + linkToSelf + '}';
         }
     }
    diff --git a/src/jdk.javadoc/share/man/javadoc.1 b/src/jdk.javadoc/share/man/javadoc.1
    index 14139d20ef2..f3a9f50a5a1 100644
    --- a/src/jdk.javadoc/share/man/javadoc.1
    +++ b/src/jdk.javadoc/share/man/javadoc.1
    @@ -21,7 +21,7 @@
     .\"
     .\" Automatically generated by Pandoc 2.3.1
     .\"
    -.TH "JAVADOC" "1" "2020" "JDK 16" "JDK Commands"
    +.TH "JAVADOC" "1" "2021" "JDK 17\-ea" "JDK Commands"
     .hy
     .SH NAME
     .PP
    @@ -596,7 +596,7 @@ it does, you must enclose the title in quotation marks.
     Additional quotation marks within the \f[CB]title\f[R] tag must be
     escaped.
     For example,
    -\f[CB]javadoc\ \-header\ "My\ Library
    v1.0"\ com.mypackage.\f[R] +\f[CB]javadoc\ \-doctitle\ "My\ Library
    v1.0"\ com.mypackage.\f[R] .RS .RE .TP diff --git a/src/jdk.jcmd/share/man/jcmd.1 b/src/jdk.jcmd/share/man/jcmd.1 index 5ab057c1453..1a3a9d7192b 100644 --- a/src/jdk.jcmd/share/man/jcmd.1 +++ b/src/jdk.jcmd/share/man/jcmd.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JCMD" "1" "2020" "JDK 16" "JDK Commands" +.TH "JCMD" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jinfo.1 b/src/jdk.jcmd/share/man/jinfo.1 index f7f79ab296e..3f2797c498f 100644 --- a/src/jdk.jcmd/share/man/jinfo.1 +++ b/src/jdk.jcmd/share/man/jinfo.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JINFO" "1" "2020" "JDK 16" "JDK Commands" +.TH "JINFO" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jmap.1 b/src/jdk.jcmd/share/man/jmap.1 index b5284e0f9e0..1e0d4ac82f6 100644 --- a/src/jdk.jcmd/share/man/jmap.1 +++ b/src/jdk.jcmd/share/man/jmap.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JMAP" "1" "2020" "JDK 16" "JDK Commands" +.TH "JMAP" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jps.1 b/src/jdk.jcmd/share/man/jps.1 index 75acc38ced0..48a503e5321 100644 --- a/src/jdk.jcmd/share/man/jps.1 +++ b/src/jdk.jcmd/share/man/jps.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JPS" "1" "2020" "JDK 16" "JDK Commands" +.TH "JPS" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jstack.1 b/src/jdk.jcmd/share/man/jstack.1 index 98269bcaf8c..578fdc7dd26 100644 --- a/src/jdk.jcmd/share/man/jstack.1 +++ b/src/jdk.jcmd/share/man/jstack.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JSTACK" "1" "2020" "JDK 16" "JDK Commands" +.TH "JSTACK" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jcmd/share/man/jstat.1 b/src/jdk.jcmd/share/man/jstat.1 index 143d3ce8d4f..00adb8dcb2c 100644 --- a/src/jdk.jcmd/share/man/jstat.1 +++ b/src/jdk.jcmd/share/man/jstat.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JSTAT" "1" "2020" "JDK 16" "JDK Commands" +.TH "JSTAT" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jconsole/share/man/jconsole.1 b/src/jdk.jconsole/share/man/jconsole.1 index 277cf034433..de039960088 100644 --- a/src/jdk.jconsole/share/man/jconsole.1 +++ b/src/jdk.jconsole/share/man/jconsole.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JCONSOLE" "1" "2020" "JDK 16" "JDK Commands" +.TH "JCONSOLE" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java index 67ab75173f8..73eb58abdaa 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java +++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/AccessFlags.java @@ -49,7 +49,7 @@ public class AccessFlags { public static final int ACC_BRIDGE = 0x0040; // method public static final int ACC_TRANSIENT = 0x0080; // field public static final int ACC_VARARGS = 0x0080; // method - public static final int ACC_INLINE = 0x0100; // class + public static final int ACC_PRIMITIVE = 0x0100; // class public static final int ACC_NATIVE = 0x0100; // method public static final int ACC_INTERFACE = 0x0200; // class, inner public static final int ACC_ABSTRACT = 0x0400; // class, inner, method @@ -83,12 +83,12 @@ public int byteLength() { } private static final int[] classModifiers = { - ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT, ACC_INLINE + ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT, ACC_PRIMITIVE }; private static final int[] classFlags = { ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, ACC_ABSTRACT, - ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE, ACC_INLINE + ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE, ACC_PRIMITIVE }; public Set getClassModifiers() { @@ -102,12 +102,12 @@ public Set getClassFlags() { private static final int[] innerClassModifiers = { ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, - ACC_ABSTRACT, ACC_INLINE + ACC_ABSTRACT, ACC_PRIMITIVE }; private static final int[] innerClassFlags = { ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SUPER, - ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_INLINE + ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_PRIMITIVE }; public Set getInnerClassModifiers() { @@ -236,7 +236,7 @@ private static String flagToName(int flag, Kind t) { case 0x80: return (t == Kind.Field ? "ACC_TRANSIENT" : "ACC_VARARGS"); case 0x100: - return (t == Kind.Class || t == Kind.InnerClass) ? "ACC_INLINE" : "ACC_NATIVE"; + return (t == Kind.Class || t == Kind.InnerClass) ? "ACC_PRIMITIVE" : "ACC_NATIVE"; case ACC_INTERFACE: return "ACC_INTERFACE"; case ACC_ABSTRACT: diff --git a/src/jdk.jdeps/share/man/javap.1 b/src/jdk.jdeps/share/man/javap.1 index 3bef06a924e..e1982398c38 100644 --- a/src/jdk.jdeps/share/man/javap.1 +++ b/src/jdk.jdeps/share/man/javap.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JAVAP" "1" "2020" "JDK 16" "JDK Commands" +.TH "JAVAP" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdeps/share/man/jdeprscan.1 b/src/jdk.jdeps/share/man/jdeprscan.1 index 3dd4cd9097e..53db8583a54 100644 --- a/src/jdk.jdeps/share/man/jdeprscan.1 +++ b/src/jdk.jdeps/share/man/jdeprscan.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JDEPRSCAN" "1" "2020" "JDK 16" "JDK Commands" +.TH "JDEPRSCAN" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdeps/share/man/jdeps.1 b/src/jdk.jdeps/share/man/jdeps.1 index 3dd37bd7150..46056c7899e 100644 --- a/src/jdk.jdeps/share/man/jdeps.1 +++ b/src/jdk.jdeps/share/man/jdeps.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JDEPS" "1" "2020" "JDK 16" "JDK Commands" +.TH "JDEPS" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jdi/share/man/jdb.1 b/src/jdk.jdi/share/man/jdb.1 index 00969b55e45..edf0ac6b4af 100644 --- a/src/jdk.jdi/share/man/jdb.1 +++ b/src/jdk.jdi/share/man/jdb.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JDB" "1" "2020" "JDK 16" "JDK Commands" +.TH "JDB" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/DeserializationEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/DeserializationEvent.java new file mode 100644 index 00000000000..7e89aa894a3 --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/events/DeserializationEvent.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.events; + +import jdk.jfr.Category; +import jdk.jfr.Description; +import jdk.jfr.Label; +import jdk.jfr.Name; +import jdk.jfr.internal.MirrorEvent; + +@Category({"Java Development Kit", "Serialization"}) +@Label("Deserialization") +@Name("jdk.Deserialization") +@Description("Results of deserialiation and ObjectInputFilter checks") +@MirrorEvent(className = "jdk.internal.event.DeserializationEvent") +public final class DeserializationEvent extends AbstractJDKEvent { + + @Label("Filter Configured") + public boolean filterConfigured; + + @Label("Filter Status") + public String filterStatus; + + @Label ("Type") + public Class type; + + @Label ("Array Length") + public int arrayLength; + + @Label ("Object References") + public long objectReferences; + + @Label ("Depth") + public long depth; + + @Label ("Bytes Read") + public long bytesRead; + + @Label ("Exception Type") + public Class exceptionType; + + @Label ("Exception Message") + public String exceptionMessage; +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java index 1a27170c6b9..a5e1d01783f 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/ChunkInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ final class ChunkInputStream extends InputStream { private final Iterator chunks; + private long unstreamedSize = 0; private RepositoryChunk currentChunk; private InputStream stream; @@ -42,6 +43,7 @@ final class ChunkInputStream extends InputStream { for (RepositoryChunk c : chunks) { c.use(); // keep alive while we're reading. l.add(c); + unstreamedSize += c.getSize(); } this.chunks = l.iterator(); @@ -50,10 +52,11 @@ final class ChunkInputStream extends InputStream { @Override public int available() throws IOException { + long total = unstreamedSize; if (stream != null) { - return stream.available(); + total += stream.available(); } - return 0; + return total <= Integer.MAX_VALUE ? (int) total : Integer.MAX_VALUE; } private boolean nextStream() throws IOException { @@ -62,6 +65,7 @@ private boolean nextStream() throws IOException { } stream = new BufferedInputStream(SecuritySupport.newFileInputStream(currentChunk.getFile())); + unstreamedSize -= currentChunk.getSize(); return true; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java index 1c27a85b812..def3545b746 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/PlatformRecording.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; @@ -851,4 +852,18 @@ public void removeBefore(Instant timestamp) { } } + + public void removePath(SafePath path) { + synchronized (recorder) { + Iterator it = chunks.iterator(); + while (it.hasNext()) { + RepositoryChunk c = it.next(); + if (c.getFile().equals(path)) { + it.remove(); + removed(c); + return; + } + } + } + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Repository.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/Repository.java index 258b5bf52fa..06a17489400 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Repository.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Repository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import java.util.Set; import jdk.jfr.internal.SecuritySupport.SafePath; +import jdk.jfr.internal.management.ChunkFilename; public final class Repository { @@ -45,6 +46,7 @@ public final class Repository { private final Set cleanupDirectories = new HashSet<>(); private SafePath baseLocation; private SafePath repository; + private ChunkFilename chunkFilename; private Repository() { } @@ -61,6 +63,7 @@ public synchronized void setBasePath(SafePath baseLocation) throws IOException { // Probe to see if repository can be created, needed for fail fast // during JVM startup or JFR.configure this.repository = createRepository(baseLocation); + this.chunkFilename = null; try { // Remove so we don't "leak" repositories, if JFR is never started // and shutdown hook not added. @@ -84,8 +87,13 @@ synchronized RepositoryChunk newChunk(ZonedDateTime timestamp) { jvm.setRepositoryLocation(repository.toString()); SecuritySupport.setProperty(JFR_REPOSITORY_LOCATION_PROPERTY, repository.toString()); cleanupDirectories.add(repository); + chunkFilename = null; } - return new RepositoryChunk(repository, timestamp); + if (chunkFilename == null) { + chunkFilename = ChunkFilename.newPriviliged(repository.toPath()); + } + String filename = chunkFilename.next(timestamp.toLocalDateTime()); + return new RepositoryChunk(new SafePath(filename), timestamp.toInstant()); } catch (Exception e) { String errorMsg = String.format("Could not create chunk in repository %s, %s: %s", repository, e.getClass(), e.getMessage()); Logger.log(LogTag.JFR, LogLevel.ERROR, errorMsg); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java index 27513ef1f9f..8ccd536a228 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/RepositoryChunk.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,6 @@ public int compare(RepositoryChunk c1, RepositoryChunk c2) { } }; - private final SafePath repositoryPath; private final SafePath chunkFile; private final Instant startTime; private final RandomAccessFile unFinishedRAF; @@ -56,28 +55,12 @@ public int compare(RepositoryChunk c1, RepositoryChunk c2) { private int refCount = 0; private long size; - RepositoryChunk(SafePath path, ZonedDateTime timestamp) throws Exception { - this.startTime = timestamp.toInstant(); - this.repositoryPath = path; - this.chunkFile = findFileName(repositoryPath, timestamp.toLocalDateTime()); + RepositoryChunk(SafePath path, Instant startTime) throws Exception { + this.startTime = startTime; + this.chunkFile = path; this.unFinishedRAF = SecuritySupport.createRandomAccessFile(chunkFile); } - private static SafePath findFileName(SafePath directory, LocalDateTime time) throws Exception { - String filename = Utils.formatDateTime(time); - Path p = directory.toPath().resolve(filename + FILE_EXTENSION); - for (int i = 1; i < MAX_CHUNK_NAMES; i++) { - SafePath s = new SafePath(p); - if (!SecuritySupport.exists(s)) { - return s; - } - String extendedName = String.format("%s_%02d%s", filename, i, FILE_EXTENSION); - p = directory.toPath().resolve(extendedName); - } - p = directory.toPath().resolve(filename + "_" + System.currentTimeMillis() + FILE_EXTENSION); - return new SafePath(p); - } - void finish(Instant endTime) { try { finishWithException(endTime); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java index 73b9a9fed8c..661d3a5b516 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -500,6 +500,11 @@ public long length(File f) throws IOException { public long fileSize(Path p) throws IOException { return doPrivilegedIOWithReturn( () -> Files.size(p)); } + + @Override + public boolean exists(Path p) throws IOException { + return doPrivilegedIOWithReturn( () -> Files.exists(p)); + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java index 49953c3ba5b..81fa5519dfa 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -184,7 +184,7 @@ public static String formatTimespan(Duration dValue, String separation) { // This method reduces the number of loaded classes // compared to DateTimeFormatter - static String formatDateTime(LocalDateTime time) { + public static String formatDateTime(LocalDateTime time) { StringBuilder sb = new StringBuilder(19); sb.append(time.getYear() / 100); appendPadded(sb, time.getYear() % 100, true); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/FileAccess.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/FileAccess.java index 92572548260..198131b61aa 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/FileAccess.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/FileAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,8 @@ public abstract class FileAccess { public abstract long fileSize(Path p) throws IOException; + public abstract boolean exists(Path s) throws IOException; + private static class UnPrivileged extends FileAccess { @Override public RandomAccessFile openRAF(File f, String mode) throws IOException { @@ -71,5 +73,10 @@ public long length(File f) throws IOException { public long fileSize(Path p) throws IOException { return Files.size(p); } + + @Override + public boolean exists(Path p) { + return Files.exists(p); + } } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java index a462bde64da..040bcf587b3 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/OngoingStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,8 +119,7 @@ private byte[] readBytes() throws IOException { throw new IOException("No progress"); } startTimeNanos += header.getDurationNanos(); - Instant timestamp = Utils.epochNanosToInstant(startTimeNanos); - ManagementSupport.removeBefore(recording, timestamp); + ManagementSupport.removePath(recording, path); closeInput(); } else { header.refresh(); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java index 82a2383c43f..50b67c51d53 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ import jdk.jfr.events.FileForceEvent; import jdk.jfr.events.FileReadEvent; import jdk.jfr.events.FileWriteEvent; +import jdk.jfr.events.DeserializationEvent; import jdk.jfr.events.ProcessStartEvent; import jdk.jfr.events.SecurityPropertyModificationEvent; import jdk.jfr.events.SocketReadEvent; @@ -55,11 +56,12 @@ public final class JDKEvents { private static final Class[] mirrorEventClasses = { + DeserializationEvent.class, + ProcessStartEvent.class, SecurityPropertyModificationEvent.class, TLSHandshakeEvent.class, X509CertificateEvent.class, - X509ValidationEvent.class, - ProcessStartEvent.class + X509ValidationEvent.class }; private static final Class[] eventClasses = { @@ -73,11 +75,13 @@ public final class JDKEvents { ErrorThrownEvent.class, ActiveSettingEvent.class, ActiveRecordingEvent.class, + jdk.internal.event.DeserializationEvent.class, + jdk.internal.event.ProcessStartEvent.class, jdk.internal.event.SecurityPropertyModificationEvent.class, jdk.internal.event.TLSHandshakeEvent.class, jdk.internal.event.X509CertificateEvent.class, jdk.internal.event.X509ValidationEvent.class, - jdk.internal.event.ProcessStartEvent.class, + DirectBufferStatisticsEvent.class }; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ChunkFilename.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ChunkFilename.java new file mode 100644 index 00000000000..3be5b69c61b --- /dev/null +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ChunkFilename.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.internal.management; + +import java.nio.file.Paths; +import java.nio.file.Path; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; + +import jdk.jfr.internal.SecuritySupport; +import jdk.jfr.internal.SecuritySupport.SafePath; +import jdk.jfr.internal.Utils; +import jdk.jfr.internal.consumer.FileAccess; + +// Allows a remote streaming client to create chunk files +// with same naming scheme as the JVM. +public final class ChunkFilename { + private static final int MAX_CHUNK_NAMES = 100_000; + private static final String FILE_EXTENSION = ".jfr"; + + private final Path directory; + private final FileAccess fileAcess; + + private Path lastPath; + private int counter; + + public static ChunkFilename newUnpriviliged(Path directory) { + return new ChunkFilename(directory, FileAccess.UNPRIVILEGED); + } + + public static ChunkFilename newPriviliged(Path directory) { + return new ChunkFilename(directory, SecuritySupport.PRIVILEGED); + } + + private ChunkFilename(Path directory, FileAccess fileAccess) { + // Avoid malicious implementations of Path interface + this.directory = Paths.get(directory.toString()); + this.fileAcess = fileAccess; + } + + public String next(LocalDateTime time) throws IOException { + String filename = Utils.formatDateTime(time); + Path p = directory.resolve(filename + FILE_EXTENSION); + + // If less than one file per second (typically case) + if (lastPath == null || !p.equals(lastPath)) { + if (!fileAcess.exists(p)) { + counter = 1; // reset counter + lastPath = p; + return p.toString(); + } + } + + // If more than one file per second + while (counter < MAX_CHUNK_NAMES) { + String extendedName = String.format("%s_%02d%s", filename, counter, FILE_EXTENSION); + p = directory.resolve(extendedName); + counter++; + if (!fileAcess.exists(p)) { + return p.toString(); + } + } + throw new IOException("Unable to find unused filename after " + counter + " attempts"); + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java index 6505364dd93..43e2b046b53 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/ManagementSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,6 +49,7 @@ import jdk.jfr.internal.MetadataRepository; import jdk.jfr.internal.PlatformRecording; import jdk.jfr.internal.PrivateAccess; +import jdk.jfr.internal.SecuritySupport.SafePath; import jdk.jfr.internal.Utils; import jdk.jfr.internal.WriteableUserPath; import jdk.jfr.internal.consumer.EventDirectoryStream; @@ -141,7 +142,12 @@ public static EventSettings newEventSettings(EventSettingsModifier esm) { public static void removeBefore(Recording recording, Instant timestamp) { PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording); pr.removeBefore(timestamp); + } + // Needed callback to detect when a chunk has been parsed. + public static void removePath(Recording recording, Path path) { + PlatformRecording pr = PrivateAccess.getInstance().getPlatformRecording(recording); + pr.removePath(new SafePath(path)); } // Needed callback to detect when a chunk has been parsed. diff --git a/src/jdk.jfr/share/conf/jfr/default.jfc b/src/jdk.jfr/share/conf/jfr/default.jfc index 49e148c4393..d70a292609a 100644 --- a/src/jdk.jfr/share/conf/jfr/default.jfc +++ b/src/jdk.jfr/share/conf/jfr/default.jfc @@ -665,6 +665,11 @@ 20 ms + + false + true + + false true diff --git a/src/jdk.jfr/share/conf/jfr/profile.jfc b/src/jdk.jfr/share/conf/jfr/profile.jfc index 5374f5b4e55..1ded1577adc 100644 --- a/src/jdk.jfr/share/conf/jfr/profile.jfc +++ b/src/jdk.jfr/share/conf/jfr/profile.jfc @@ -665,6 +665,11 @@ 10 ms + + false + true + + false true diff --git a/src/jdk.jfr/share/man/jfr.1 b/src/jdk.jfr/share/man/jfr.1 index 0fb8912b671..cb63d227d6a 100644 --- a/src/jdk.jfr/share/man/jfr.1 +++ b/src/jdk.jfr/share/man/jfr.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JFR" "1" "2020" "JDK 16" "JDK Commands" +.TH "JFR" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java index 8ec9c3df61b..749025bea9d 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java @@ -133,7 +133,7 @@ public static void recreateJimage(Path jimageFile, Archive::moduleName, a -> { try (Stream entries = a.entries()) { - return entries.collect(Collectors.toList()); + return entries.toList(); } })); ByteOrder order = ByteOrder.nativeOrder(); diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java index 3222bc53aae..ce93b4a06fe 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java @@ -29,7 +29,6 @@ import java.lang.module.ModuleDescriptor; import java.nio.ByteOrder; import java.util.*; -import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.internal.jimage.decompressor.Decompressor; @@ -149,7 +148,7 @@ private List getSortedStrings() { Comparator.reverseOrder())).filter((e) -> { return e.getValue() > 1; }).map(java.util.Map.Entry::getKey). - collect(Collectors.toList()); + toList(); return result; } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java index 0e8dc45b933..229076c1f0c 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java @@ -38,7 +38,6 @@ import java.util.List; import java.util.ArrayList; import java.util.Arrays; -import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.Collections; import java.util.Locale; @@ -566,7 +565,7 @@ public List handleOptions(T task, String[] args) throws BadArgs { if (option.isTerminal()) { return ++i < args.length ? Stream.of(Arrays.copyOfRange(args, i, args.length)) - .collect(Collectors.toList()) + .toList() : Collections.emptyList(); } @@ -576,7 +575,7 @@ public List handleOptions(T task, String[] args) throws BadArgs { } } else { return Stream.of(Arrays.copyOfRange(args, i, args.length)) - .collect(Collectors.toList()); + .toList(); } } return Collections.emptyList(); diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java index c91e7f9052d..0301e980e66 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Utils.java @@ -33,7 +33,6 @@ import java.util.Arrays; import java.util.Comparator; import java.util.List; -import java.util.stream.Collectors; import jdk.tools.jlink.plugin.Plugin; @@ -51,7 +50,7 @@ public static List parseList(String arguments) { return Arrays.stream(arguments.split(",")) .map((p) -> p.trim()) .filter((p) -> !p.isEmpty()) - .collect(Collectors.toList()); + .toList(); } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java index b2a759a0ad4..cdd0167eb6e 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java @@ -34,7 +34,6 @@ import java.util.Map; import java.util.TreeSet; import java.util.function.Predicate; -import java.util.stream.Collectors; import jdk.tools.jlink.internal.Platform; import jdk.tools.jlink.plugin.PluginException; @@ -106,7 +105,7 @@ private List getVMs(ResourcePoolModule javaBase, String[] jvm } } return false; - }).collect(Collectors.toList()); + }).toList(); return ret; } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java index 8d327530d91..17062af55f3 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java @@ -219,7 +219,7 @@ public void previsit(ResourcePool resources, StringTable strings) { .distinct() .sorted() .map(IncludeLocalesPlugin::tagToLocale) - .collect(Collectors.toList()); + .toList(); } else { // jdk.localedata is not added. throw new PluginException(PluginsResourceBundle.getMessage(getName() + ".localedatanotfound")); @@ -236,7 +236,7 @@ public void previsit(ResourcePool resources, StringTable strings) { META_FILES.stream(), filtered.stream().flatMap(s -> includeLocaleFilePatterns(s).stream())) .map(s -> "regex:" + s) - .collect(Collectors.toList()); + .toList(); predicate = ResourceFilter.includeFilter(value); } @@ -266,7 +266,7 @@ private List includeLocaleFilePatterns(String tag) { private List includeLocaleFiles(String localeStr) { return INCLUDE_LOCALE_FILES.stream() .map(s -> s + localeStr + ".class") - .collect(Collectors.toList()); + .toList(); } private boolean stripUnsupportedLocales(byte[] bytes, ClassReader cr) { @@ -299,7 +299,7 @@ private boolean filterOutUnsupportedTags(byte[] b) { locales = originalTags.stream() .filter(tag -> !tag.isEmpty()) .map(IncludeLocalesPlugin::tagToLocale) - .collect(Collectors.toList()); + .toList(); } catch (IllformedLocaleException ile) { // Seems not an available locales string literal. return false; @@ -342,7 +342,7 @@ private List filterLocales(List locales) { .flatMap(Optional::stream) .flatMap(IncludeLocalesPlugin::localeToTags) .distinct() - .collect(Collectors.toList()); + .toList(); return ret; } diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java index 737e85cfa68..88f5a0eb7ce 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StringSharingPlugin.java @@ -51,7 +51,6 @@ import java.util.Map; import java.util.Set; import java.util.function.Predicate; -import java.util.stream.Collectors; import jdk.internal.jimage.decompressor.CompressIndexes; import jdk.internal.jimage.decompressor.SignatureParser; import jdk.internal.jimage.decompressor.StringSharingDecompressor; @@ -264,7 +263,7 @@ private byte[] optimize(ResourcePoolEntry resource, ResourcePoolBuilder resource List indexes = parseResult.types.stream().map((type) -> { return strings.addString(type); - }).collect(Collectors.toList()); + }).toList(); if (!indexes.isEmpty()) { out.write(StringSharingDecompressor.EXTERNALIZED_STRING_DESCRIPTOR); int sigIndex = strings.addString(parseResult.formatted); diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java index a1a1836f87f..8ff4bfee78f 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModulesPlugin.java @@ -291,7 +291,7 @@ private List sublist(List moduleInfos, Configuration cf) .collect(Collectors.toSet()); return moduleInfos.stream() .filter(mi -> names.contains(mi.moduleName())) - .collect(Collectors.toList()); + .toList(); } /** diff --git a/src/jdk.jlink/share/man/jlink.1 b/src/jdk.jlink/share/man/jlink.1 index a782d558b43..9fa2785fef6 100644 --- a/src/jdk.jlink/share/man/jlink.1 +++ b/src/jdk.jlink/share/man/jlink.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JLINK" "1" "2020" "JDK 16" "JDK Commands" +.TH "JLINK" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jlink/share/man/jmod.1 b/src/jdk.jlink/share/man/jmod.1 index d46f8708478..b512895990b 100644 --- a/src/jdk.jlink/share/man/jmod.1 +++ b/src/jdk.jlink/share/man/jmod.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JMOD" "1" "2020" "JDK 16" "JDK Commands" +.TH "JMOD" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppImageBuilder.java b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppImageBuilder.java index b5d602afe65..57f0c4feeff 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppImageBuilder.java +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/LinuxAppImageBuilder.java @@ -83,6 +83,9 @@ public void prepareApplicationFiles(Map params) // create the primary launcher createLauncherForEntryPoint(params, null); + // create app launcher shared library + createLauncherLib(); + // create the additional launchers, if any List> entryPoints = ADD_LAUNCHERS.fetchFrom(params); @@ -95,6 +98,17 @@ public void prepareApplicationFiles(Map params) copyApplication(params); } + private void createLauncherLib() throws IOException { + Path path = appLayout.pathGroup().getPath( + ApplicationLayout.PathRole.LINUX_APPLAUNCHER_LIB); + try (InputStream resource = getResourceAsStream("libjpackageapplauncher.so")) { + writeEntry(resource, path); + } + + path.toFile().setExecutable(true, false); + path.toFile().setWritable(true, true); + } + private void createLauncherForEntryPoint(Map params, Map mainParams) throws IOException { // Copy executable to launchers folder diff --git a/src/jdk.jpackage/linux/native/applauncher/LinuxLauncher.c b/src/jdk.jpackage/linux/native/applauncher/LinuxLauncher.c new file mode 100644 index 00000000000..7990fba0248 --- /dev/null +++ b/src/jdk.jpackage/linux/native/applauncher/LinuxLauncher.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "JvmLauncher.h" +#include "LinuxPackage.h" + + +#define STATUS_FAILURE 1 + +typedef JvmlLauncherHandle (*JvmlLauncherAPI_CreateFunType)(int argc, char *argv[]); + +static int appArgc; +static char **appArgv; + + +static JvmlLauncherData* initJvmlLauncherData(void) { + char* launcherLibPath = 0; + void* jvmLauncherLibHandle = 0; + JvmlLauncherAPI_GetAPIFunc getApi = 0; + JvmlLauncherAPI_CreateFunType createJvmlLauncher = 0; + JvmlLauncherAPI* api = 0; + JvmlLauncherHandle jvmLauncherHandle = 0; + JvmlLauncherData* result = 0; + + launcherLibPath = getJvmLauncherLibPath(); + if (!launcherLibPath) { + goto cleanup; + } + + jvmLauncherLibHandle = dlopen(launcherLibPath, RTLD_NOW | RTLD_LOCAL); + if (!jvmLauncherLibHandle) { + JP_LOG_ERRMSG(dlerror()); + goto cleanup; + } + + getApi = dlsym(jvmLauncherLibHandle, "jvmLauncherGetAPI"); + if (!getApi) { + JP_LOG_ERRMSG(dlerror()); + goto cleanup; + } + + api = (*getApi)(); + if (!api) { + JP_LOG_ERRMSG("Failed to get JvmlLauncherAPI instance"); + goto cleanup; + } + + createJvmlLauncher = dlsym(jvmLauncherLibHandle, "jvmLauncherCreate"); + if (!createJvmlLauncher) { + JP_LOG_ERRMSG(dlerror()); + goto cleanup; + } + + jvmLauncherHandle = (*createJvmlLauncher)(appArgc, appArgv); + if (!jvmLauncherHandle) { + goto cleanup; + } + + result = jvmLauncherCreateJvmlLauncherData(api, jvmLauncherHandle); + /* Handle released in jvmLauncherCreateJvmlLauncherData() */ + jvmLauncherHandle = 0; + +cleanup: + if (jvmLauncherHandle) { + jvmLauncherCloseHandle(api, jvmLauncherHandle); + } + if (jvmLauncherLibHandle) { + dlclose(jvmLauncherLibHandle); + } + free(launcherLibPath); + + return result; +} + + +static int launchJvm(JvmlLauncherData* cfg) { + void* jliLibHandle = 0; + void* JLI_Launch; + int exitCode = STATUS_FAILURE; + + jliLibHandle = dlopen(cfg->jliLibPath, RTLD_NOW | RTLD_LOCAL); + if (!jliLibHandle) { + JP_LOG_ERRMSG(dlerror()); + goto cleanup; + } + + JLI_Launch = dlsym(jliLibHandle, "JLI_Launch"); + if (!JLI_Launch) { + JP_LOG_ERRMSG(dlerror()); + goto cleanup; + } + + exitCode = jvmLauncherStartJvm(cfg, JLI_Launch); + +cleanup: + if (jliLibHandle) { + dlclose(jliLibHandle); + } + + return exitCode; +} + + +int main(int argc, char *argv[]) { + int exitCode = STATUS_FAILURE; + JvmlLauncherData* jvmLauncherData; + + appArgc = argc; + appArgv = argv; + + jvmLauncherData = initJvmlLauncherData(); + if (jvmLauncherData) { + exitCode = launchJvm(jvmLauncherData); + free(jvmLauncherData); + } + + return exitCode; +} diff --git a/src/jdk.jpackage/linux/native/applauncher/LinuxPackage.c b/src/jdk.jpackage/linux/native/applauncher/LinuxPackage.c new file mode 100644 index 00000000000..5e3ef362d2e --- /dev/null +++ b/src/jdk.jpackage/linux/native/applauncher/LinuxPackage.c @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "JvmLauncher.h" +#include "LinuxPackage.h" + + +static char* getModulePath(void) { + char modulePath[PATH_MAX] = { 0 }; + ssize_t modulePathLen = 0; + char* result = 0; + + modulePathLen = readlink("/proc/self/exe", modulePath, + sizeof(modulePath) - 1); + if (modulePathLen < 0) { + JP_LOG_ERRNO; + return 0; + } + modulePath[modulePathLen] = '\0'; + result = strdup(modulePath); + if (!result) { + JP_LOG_ERRNO; + } + + return result; +} + + +# define PACKAGE_TYPE_UNKNOWN 0 +# define PACKAGE_TYPE_RPM 1 +# define PACKAGE_TYPE_DEB 2 + +typedef struct { + char* name; + int type; +} PackageDesc; + + +static void freePackageDesc(PackageDesc* desc) { + if (desc) { + free(desc->name); + free(desc); + } +} + + +static PackageDesc* createPackageDesc(void) { + PackageDesc* result = 0; + + result = malloc(sizeof(PackageDesc)); + if (!result) { + JP_LOG_ERRNO; + goto cleanup; + } + + result->type = PACKAGE_TYPE_UNKNOWN; + result->name = 0; + +cleanup: + return result; +} + + +static PackageDesc* initPackageDesc(PackageDesc* desc, const char* str, + int type) { + char *newStr = strdup(str); + if (!newStr) { + JP_LOG_ERRNO; + return 0; + } + + free(desc->name); + desc->name = newStr; + desc->type = type; + return desc; +} + + +#define POPEN_CALLBACK_USE 1 +#define POPEN_CALLBACK_IGNORE 0 + +typedef int (*popenCallbackType)(void*, const char*); + +static int popenCommand(const char* cmdlineFormat, const char* arg, + popenCallbackType callback, void* callbackData) { + char* cmdline = 0; + FILE *stream = 0; + const size_t cmdlineLenth = strlen(cmdlineFormat) + strlen(arg); + char* strBufBegin = 0; + char* strBufEnd = 0; + char* strBufNextChar = 0; + char* strNewBufBegin = 0; + size_t strBufCapacity = 0; + int callbackMode = POPEN_CALLBACK_USE; + int exitCode = -1; + int c; + + cmdline = malloc(cmdlineLenth + 1 /* \0 */); + if (!cmdline) { + JP_LOG_ERRNO; + goto cleanup; + } + +#if defined(__GNUC__) && __GNUC__ >= 5 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif + if (0 > snprintf(cmdline, cmdlineLenth, cmdlineFormat, arg)) { + JP_LOG_ERRNO; + goto cleanup; + } +#if defined(__GNUC__) && __GNUC__ >= 5 +#pragma GCC diagnostic pop +#endif + + JP_LOG_TRACE("popen: (%s)", cmdline); + + stream = popen(cmdline, "r"); + if (!stream) { + JP_LOG_ERRNO; + goto cleanup; + } + + for (;;) { + c = fgetc(stream); + if((EOF == c || '\n' == c)) { + if (POPEN_CALLBACK_USE == callbackMode + && strBufBegin != strBufNextChar) { + *strBufNextChar = 0; + JP_LOG_TRACE("popen: [%s]", strBufBegin); + callbackMode = (*callback)(callbackData, strBufBegin); + strBufNextChar = strBufBegin; + } + + if (EOF == c) { + break; + } + + continue; + } + + if (strBufNextChar == strBufEnd) { + /* Double buffer size */ + strBufCapacity = strBufCapacity * 2 + 1; + strNewBufBegin = realloc(strBufBegin, strBufCapacity); + if (!strNewBufBegin) { + JP_LOG_ERRNO; + goto cleanup; + } + + strBufNextChar = strNewBufBegin + (strBufNextChar - strBufBegin); + strBufEnd = strNewBufBegin + strBufCapacity; + strBufBegin = strNewBufBegin; + } + + *strBufNextChar++ = (char)c; + } + +cleanup: + if (stream) { + exitCode = pclose(stream); + } + + if (strBufBegin) { + free(strBufBegin); + } + + free(cmdline); + + JP_LOG_TRACE("popen: exit: %d", exitCode); + return exitCode; +} + + +static char* concat(const char *x, const char *y) { + const size_t lenX = strlen(x); + const size_t lenY = strlen(y); + + char *result = malloc(lenX + lenY + 1 /* \0 */); + if (!result) { + JP_LOG_ERRNO; + } else { + strcpy(result, x); + strcat(result, y); + } + + return result; +} + + +static int initRpmPackage(void* desc, const char* str) { + initPackageDesc((PackageDesc*)desc, str, PACKAGE_TYPE_RPM); + return POPEN_CALLBACK_IGNORE; +} + + +static int initDebPackage(void* desc, const char* str) { + char* colonChrPos = strchr(str, ':'); + if (colonChrPos) { + *colonChrPos = 0; + } + initPackageDesc((PackageDesc*)desc, str, PACKAGE_TYPE_DEB); + return POPEN_CALLBACK_IGNORE; +} + + +#define LAUNCHER_LIB_NAME "/libapplauncher.so" + +static int findLauncherLib(void* launcherLibPath, const char* str) { + char* buf = 0; + const size_t strLen = strlen(str); + const size_t launcherLibNameLen = strlen(LAUNCHER_LIB_NAME); + + if (launcherLibNameLen <= strLen + && !strcmp(str + strLen - launcherLibNameLen, LAUNCHER_LIB_NAME)) { + buf = strdup(str); + if (!buf) { + JP_LOG_ERRNO; + } else { + *(char**)launcherLibPath = buf; + } + return POPEN_CALLBACK_IGNORE; + } + return POPEN_CALLBACK_USE; +} + + +static PackageDesc* findOwnerOfFile(const char* path) { + int popenStatus = -1; + PackageDesc* pkg = 0; + + pkg = createPackageDesc(); + if (!pkg) { + return 0; + } + + popenStatus = popenCommand( + "rpm --queryformat '%{NAME}' -qf '%s' 2>/dev/null", path, + initRpmPackage, pkg); + if (popenStatus) { + pkg->type = PACKAGE_TYPE_UNKNOWN; + popenStatus = popenCommand("dpkg -S '%s' 2>/dev/null", path, + initDebPackage, pkg); + } + + if (popenStatus) { + pkg->type = PACKAGE_TYPE_UNKNOWN; + } + + if (PACKAGE_TYPE_UNKNOWN == pkg->type || !pkg->name) { + freePackageDesc(pkg); + pkg = 0; + } + + if (pkg) { + JP_LOG_TRACE("owner pkg: (%s|%d)", pkg->name, pkg->type); + } + + return pkg; +} + + +char* getJvmLauncherLibPath(void) { + char* modulePath = 0; + char* appImageDir = 0; + char* launcherLibPath = 0; + const char* pkgQueryCmd = 0; + int popenStatus = -1; + PackageDesc* pkg = 0; + + modulePath = getModulePath(); + if (!modulePath) { + goto cleanup; + } + + pkg = findOwnerOfFile(modulePath); + if (!pkg) { + /* Not a package install */ + /* Launcher should be in "bin" subdirectory of app image. */ + /* Launcher lib should be in "lib" subdirectory of app image. */ + appImageDir = dirname(dirname(modulePath)); + launcherLibPath = concat(appImageDir, "/lib" LAUNCHER_LIB_NAME); + } else { + if (PACKAGE_TYPE_RPM == pkg->type) { + pkgQueryCmd = "rpm -ql '%s' 2>/dev/null"; + } else if (PACKAGE_TYPE_DEB == pkg->type) { + pkgQueryCmd = "dpkg -L '%s' 2>/dev/null"; + } else { + /* Should never happen */ + JP_LOG_ERRMSG("Internal error"); + goto cleanup; + } + + popenStatus = popenCommand(pkgQueryCmd, pkg->name, findLauncherLib, + &launcherLibPath); + if (popenStatus) { + free(launcherLibPath); + launcherLibPath = NULL; + goto cleanup; + } + } + +cleanup: + free(modulePath); + freePackageDesc(pkg); + + return launcherLibPath; +} diff --git a/src/jdk.jpackage/linux/native/applauncher/LinuxPackage.h b/src/jdk.jpackage/linux/native/applauncher/LinuxPackage.h new file mode 100644 index 00000000000..24ec1891066 --- /dev/null +++ b/src/jdk.jpackage/linux/native/applauncher/LinuxPackage.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef LinuxPackage_h +#define LinuxPackage_h + +#ifdef __cplusplus +extern "C" { +#endif + +char* getJvmLauncherLibPath(void); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef LinuxPackage_h */ diff --git a/src/jdk.jpackage/linux/native/applauncher/Executor.cpp b/src/jdk.jpackage/linux/native/libapplauncher/Executor.cpp similarity index 100% rename from src/jdk.jpackage/linux/native/applauncher/Executor.cpp rename to src/jdk.jpackage/linux/native/libapplauncher/Executor.cpp diff --git a/src/jdk.jpackage/linux/native/applauncher/Executor.h b/src/jdk.jpackage/linux/native/libapplauncher/Executor.h similarity index 100% rename from src/jdk.jpackage/linux/native/applauncher/Executor.h rename to src/jdk.jpackage/linux/native/libapplauncher/Executor.h diff --git a/src/jdk.jpackage/linux/native/applauncher/LinuxLauncher.cpp b/src/jdk.jpackage/linux/native/libapplauncher/LinuxLauncherLib.cpp similarity index 86% rename from src/jdk.jpackage/linux/native/applauncher/LinuxLauncher.cpp rename to src/jdk.jpackage/linux/native/libapplauncher/LinuxLauncherLib.cpp index 8aa497f59c7..f93bb7512e4 100644 --- a/src/jdk.jpackage/linux/native/applauncher/LinuxLauncher.cpp +++ b/src/jdk.jpackage/linux/native/libapplauncher/LinuxLauncherLib.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,8 +23,10 @@ * questions. */ -#include -#include +#include "kludge_c++11.h" + +#include +#include "JvmLauncher.h" #include "AppLauncher.h" #include "FileUtils.h" #include "UnixSysInfo.h" @@ -44,6 +46,8 @@ size_t hash(const std::string& str) { return h; } +Jvm* jvmLauncher; + void launchApp() { const tstring launcherPath = SysInfo::getProcessModulePath(); @@ -116,14 +120,38 @@ void launchApp() { } JP_CATCH_ALL; - appLauncher.launch(); + jvmLauncher = appLauncher.createJvmLauncher(); } } // namespace -int main(int argc, char *argv[]) { +extern "C" { + +JNIEXPORT JvmlLauncherHandle jvmLauncherCreate(int argc, char *argv[]) { SysInfo::argc = argc; SysInfo::argv = argv; - return app::launch(std::nothrow, launchApp); + jvmLauncher = 0; + app::launch(std::nothrow, launchApp); + + JvmlLauncherHandle jlh = 0; + if (jvmLauncher) { + jlh = jvmLauncher->exportLauncher(); + const std::unique_ptr deleter(jvmLauncher); + } + + return jlh; } + +} // extern "C" + + +namespace { + +void dcon() __attribute__((destructor)); + +void dcon() { + LOG_TRACE("unload"); +} + +} // namespace diff --git a/src/jdk.jpackage/linux/native/applauncher/Package.cpp b/src/jdk.jpackage/linux/native/libapplauncher/Package.cpp similarity index 100% rename from src/jdk.jpackage/linux/native/applauncher/Package.cpp rename to src/jdk.jpackage/linux/native/libapplauncher/Package.cpp diff --git a/src/jdk.jpackage/linux/native/applauncher/Package.h b/src/jdk.jpackage/linux/native/libapplauncher/Package.h similarity index 100% rename from src/jdk.jpackage/linux/native/applauncher/Package.h rename to src/jdk.jpackage/linux/native/libapplauncher/Package.h diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationLayout.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationLayout.java index c725afed3a1..ceb0e3f7e72 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationLayout.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationLayout.java @@ -62,6 +62,11 @@ enum PathRole { * Directory with application Java modules. */ MODULES, + + /** + * Linux app launcher shared library. + */ + LINUX_APPLAUNCHER_LIB } ApplicationLayout(Map paths) { @@ -131,7 +136,8 @@ static ApplicationLayout linuxAppImage() { PathRole.RUNTIME, Path.of("lib/runtime"), PathRole.RUNTIME_HOME, Path.of("lib/runtime"), PathRole.DESKTOP, Path.of("lib"), - PathRole.MODULES, Path.of("lib/app/mods") + PathRole.MODULES, Path.of("lib/app/mods"), + PathRole.LINUX_APPLAUNCHER_LIB, Path.of("lib/libapplauncher.so") )); } @@ -186,7 +192,9 @@ public static ApplicationLayout linuxUsrTreePackageImage(Path prefix, PathRole.RUNTIME, lib.resolve("runtime"), PathRole.RUNTIME_HOME, lib.resolve("runtime"), PathRole.DESKTOP, lib, - PathRole.MODULES, lib.resolve("app/mods") + PathRole.MODULES, lib.resolve("app/mods"), + PathRole.LINUX_APPLAUNCHER_LIB, lib.resolve( + "lib/libapplauncher.so") )); } diff --git a/src/jdk.jpackage/share/man/jpackage.1 b/src/jdk.jpackage/share/man/jpackage.1 index 8fa4a24005b..b8ea1ae09d4 100644 --- a/src/jdk.jpackage/share/man/jpackage.1 +++ b/src/jdk.jpackage/share/man/jpackage.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JPACKAGE" "1" "2019" "JDK 16" "JDK Commands" +.TH "JPACKAGE" "1" "2019" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jpackage/share/native/applauncher/JvmLauncher.cpp b/src/jdk.jpackage/share/native/applauncher/JvmLauncher.cpp index 96cc6745bd4..d3d15965fe2 100644 --- a/src/jdk.jpackage/share/native/applauncher/JvmLauncher.cpp +++ b/src/jdk.jpackage/share/native/applauncher/JvmLauncher.cpp @@ -24,7 +24,7 @@ */ #include -#include +#include "tstrings.h" #include "JvmLauncher.h" #include "Log.h" #include "Dll.h" @@ -39,11 +39,21 @@ #define LAUNCH_FUNC "JLI_Launch" #endif +Jvm::Jvm() { + LOG_TRACE(tstrings::any() << "Jvm(" << this << ")::Jvm()"); +} + + +Jvm::~Jvm() { + LOG_TRACE(tstrings::any() << "Jvm(" << this << ")::~Jvm()"); +} + + Jvm& Jvm::initFromConfigFile(const CfgFile& cfgFile) { const CfgFile::Properties& appOptions = cfgFile.getProperties( SectionName::Application); - do { + { const CfgFile::Properties::const_iterator modulepath = appOptions.find( PropertyName::modulepath); if (modulepath != appOptions.end()) { @@ -54,18 +64,18 @@ Jvm& Jvm::initFromConfigFile(const CfgFile& cfgFile) { addArgument(*it); }; } - } while (0); + } - do { + { const CfgFile::Properties::const_iterator classpath = appOptions.find( PropertyName::classpath); if (classpath != appOptions.end()) { addArgument(_T("-classpath")); addArgument(CfgFile::asPathList(*classpath)); } - } while (0); + } - do { + { const CfgFile::Properties::const_iterator splash = appOptions.find( PropertyName::splash); if (splash != appOptions.end()) { @@ -78,9 +88,9 @@ Jvm& Jvm::initFromConfigFile(const CfgFile& cfgFile) { << splashPath << "\" not found"); } } - } while (0); + } - do { + { const CfgFile::Properties& section = cfgFile.getProperties( SectionName::JavaOptions); const CfgFile::Properties::const_iterator javaOptions = section.find( @@ -92,44 +102,44 @@ Jvm& Jvm::initFromConfigFile(const CfgFile& cfgFile) { addArgument(*it); }; } - } while (0); + } - do { + { addArgument(_T("-Djpackage.app-path=") + SysInfo::getProcessModulePath()); - } while (0); + } // No validation of data in config file related to how Java app should be // launched intentionally. // Just read what is in config file and put on jvm's command line as is. - do { // Run modular app + { // Run modular app const CfgFile::Properties::const_iterator mainmodule = appOptions.find( PropertyName::mainmodule); if (mainmodule != appOptions.end()) { addArgument(_T("-m")); addArgument(CfgFile::asString(*mainmodule)); } - } while (0); + } - do { // Run main class + { // Run main class const CfgFile::Properties::const_iterator mainclass = appOptions.find( PropertyName::mainclass); if (mainclass != appOptions.end()) { addArgument(CfgFile::asString(*mainclass)); } - } while (0); + } - do { // Run jar + { // Run jar const CfgFile::Properties::const_iterator mainjar = appOptions.find( PropertyName::mainjar); if (mainjar != appOptions.end()) { addArgument(_T("-jar")); addArgument(CfgFile::asString(*mainjar)); } - } while (0); + } - do { + { const CfgFile::Properties& section = cfgFile.getProperties( SectionName::ArgOptions); const CfgFile::Properties::const_iterator arguments = section.find( @@ -141,7 +151,7 @@ Jvm& Jvm::initFromConfigFile(const CfgFile& cfgFile) { addArgument(*it); }; } - } while (0); + } return *this; } @@ -160,69 +170,191 @@ bool Jvm::isWithSplash() const { namespace { -void convertArgs(const std::vector& args, std::vector& argv) { - argv.reserve(args.size() + 1); - argv.resize(0); - std::vector::const_iterator it = args.begin(); - const std::vector::const_iterator end = args.end(); +struct JvmlLauncherHandleCloser { + typedef JvmlLauncherHandle pointer; - for (; it != end; ++it) { - argv.push_back(const_cast(it->c_str())); - }; + void operator()(JvmlLauncherHandle h) { + jvmLauncherCloseHandle(jvmLauncherGetAPI(), h); + } +}; + +struct JvmlLauncherDataDeleter { + typedef JvmlLauncherData* pointer; + + void operator()(JvmlLauncherData* ptr) { + free(ptr); + } +}; - // Add treminal '0'. - argv.push_back(0); -} } // namespace void Jvm::launch() { - typedef int (JNICALL *LaunchFuncType)(int argc, char ** argv, - int jargc, const char** jargv, - int appclassc, const char** appclassv, - const char* fullversion, - const char* dotversion, - const char* pname, - const char* lname, - jboolean javaargs, - jboolean cpwildcard, - jboolean javaw, - jint ergo); - - std::vector argv; + typedef std::unique_ptr< + JvmlLauncherHandle, JvmlLauncherHandleCloser> AutoJvmlLauncherHandle; + + typedef std::unique_ptr< + JvmlLauncherData, JvmlLauncherDataDeleter> AutoJvmlLauncherData; + + AutoJvmlLauncherHandle jlh(exportLauncher()); + + JvmlLauncherAPI* api = jvmLauncherGetAPI(); + + AutoJvmlLauncherData jld(jvmLauncherCreateJvmlLauncherData(api, + jlh.release())); + + LOG_TRACE(tstrings::any() << "JVM library: \"" << jvmPath << "\""); + + DllFunction func(Dll(jvmPath), LAUNCH_FUNC); + + int exitStatus = jvmLauncherStartJvm(jld.get(), func.operator void*()); + + if (exitStatus != 0) { + JP_THROW("Failed to launch JVM"); + } +} + + +namespace { + +struct JliLaunchData { + std::string jliLibPath; + std::vector args; + + int initJvmlLauncherData(JvmlLauncherData* ptr, int bufferSize) const { + int minimalBufferSize = initJvmlLauncherData(0); + if (minimalBufferSize <= bufferSize) { + initJvmlLauncherData(ptr); + } + return minimalBufferSize; + } + +private: + int initJvmlLauncherData(JvmlLauncherData* ptr) const { + // Store path to JLI library just behind JvmlLauncherData header. + char* curPtr = reinterpret_cast(ptr + 1); + { + const size_t count = sizeof(char) + * (jliLibPath.size() + 1 /* trailing zero */); + if (ptr) { + std::memcpy(curPtr, jliLibPath.c_str(), count); + ptr->jliLibPath = curPtr; + } + curPtr += count; + } + + // Next write array of char* pointing to JLI lib arg strings. + if (ptr) { + ptr->jliLaunchArgv = reinterpret_cast(curPtr); + ptr->jliLaunchArgc = (int)args.size(); + // Add terminal '0' arg. + ptr->jliLaunchArgv[ptr->jliLaunchArgc] = 0; + } + + // Skip memory occupied by char* array. + curPtr += sizeof(char*) * (args.size() + 1 /* terminal '0' arg */); + + // Store array of strings. + for (size_t i = 0; i != args.size(); i++) { + const size_t count = (args[i].size() + 1 /* trailing zero */); + if (ptr) { + std::memcpy(curPtr, args[i].c_str(), count); + ptr->jliLaunchArgv[i] = curPtr; + } + curPtr += count; + }; + + const size_t bufferSize = curPtr - reinterpret_cast(ptr); + if (ptr) { + LOG_TRACE(tstrings::any() << "Initialized " << bufferSize + << " bytes at " << ptr << " address"); + } else { + LOG_TRACE(tstrings::any() << "Need " << bufferSize + << " bytes for JvmlLauncherData buffer"); + } + return static_cast(bufferSize); + } +}; + +} // namespace + +JvmlLauncherHandle Jvm::exportLauncher() const { + std::unique_ptr result(new JliLaunchData()); + + result->jliLibPath = tstrings::toUtf8(jvmPath); + #ifdef TSTRINGS_WITH_WCHAR - std::vector mbcs_args; - do { + { tstring_array::const_iterator it = args.begin(); const tstring_array::const_iterator end = args.end(); for (; it != end; ++it) { - mbcs_args.push_back(tstrings::toACP(*it)); + result->args.push_back(tstrings::toACP(*it)); } - } while (0); - convertArgs(mbcs_args, argv); + } #else - convertArgs(args, argv); + result->args = args; #endif - // Don't count terminal '0'. - const int argc = (int)argv.size() - 1; + return result.release(); +} - LOG_TRACE(tstrings::any() << "JVM library: \"" << jvmPath << "\""); - DllFunction func(Dll(jvmPath), LAUNCH_FUNC); - int exitStatus = func(argc, argv.data(), - 0, 0, - 0, 0, - "", - "", - "java", - "java", - JNI_FALSE, - JNI_FALSE, - JNI_FALSE, - 0); +namespace { - if (exitStatus != 0) { - JP_THROW("Failed to launch JVM"); +void closeHandle(JvmlLauncherHandle h) { + JP_TRY; + + JliLaunchData* data = static_cast(h); + const std::unique_ptr deleter(data); + + JP_CATCH_ALL; +} + + +int getJvmlLauncherDataSize(JvmlLauncherHandle h) { + JP_TRY; + + const JliLaunchData* data = static_cast(h); + return data->initJvmlLauncherData(0, 0); + + JP_CATCH_ALL; + + return -1; +} + + +JvmlLauncherData* initJvmlLauncherData(JvmlLauncherHandle h, + void* ptr, int bufferSize) { + JP_TRY; + + const JliLaunchData* data = static_cast(h); + const int usedBufferSize = data->initJvmlLauncherData( + static_cast(ptr), bufferSize); + if (bufferSize <= usedBufferSize) { + return static_cast(ptr); } + + JP_CATCH_ALL; + + return 0; +} + +class Impl : public JvmlLauncherAPI { +public: + Impl() { + this->closeHandle = ::closeHandle; + this->getJvmlLauncherDataSize = ::getJvmlLauncherDataSize; + this->initJvmlLauncherData = ::initJvmlLauncherData; + } +} api; + +} // namespace + + +extern "C" { + +JNIEXPORT JvmlLauncherAPI* jvmLauncherGetAPI(void) { + return &api; } + +} // extern "C" diff --git a/src/jdk.jpackage/share/native/applauncher/JvmLauncher.h b/src/jdk.jpackage/share/native/applauncher/JvmLauncher.h index 1cd7ef9b87b..8b099807976 100644 --- a/src/jdk.jpackage/share/native/applauncher/JvmLauncher.h +++ b/src/jdk.jpackage/share/native/applauncher/JvmLauncher.h @@ -27,6 +27,67 @@ #ifndef JvmLauncher_h #define JvmLauncher_h + +#include "jni.h" /* JNIEXPORT */ + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + const char* jliLibPath; + int jliLaunchArgc; + char** jliLaunchArgv; +} JvmlLauncherData; + +typedef void* JvmlLauncherHandle; + +typedef void (*JvmlLauncherAPI_CloseHandleFunc)(JvmlLauncherHandle); +typedef int (*JvmlLauncherAPI_GetJvmlLauncherDataSizeFunc)(JvmlLauncherHandle); +typedef JvmlLauncherData* (*JvmlLauncherAPI_InitJvmlLauncherDataFunc)(JvmlLauncherHandle, void*, int); + +typedef struct { + JvmlLauncherAPI_CloseHandleFunc closeHandle; + JvmlLauncherAPI_GetJvmlLauncherDataSizeFunc getJvmlLauncherDataSize; + JvmlLauncherAPI_InitJvmlLauncherDataFunc initJvmlLauncherData; +} JvmlLauncherAPI; + +typedef JvmlLauncherAPI* (*JvmlLauncherAPI_GetAPIFunc)(void); + +JNIEXPORT JvmlLauncherAPI* jvmLauncherGetAPI(void); + +static inline void jvmLauncherCloseHandle(JvmlLauncherAPI* api, JvmlLauncherHandle h) { + (*api->closeHandle)(h); +} + +static inline int jvmLauncherGetJvmlLauncherDataSize(JvmlLauncherAPI* api, + JvmlLauncherHandle h) { + return (*api->getJvmlLauncherDataSize)(h); +} + +static inline JvmlLauncherData* jvmLauncherInitJvmlLauncherData(JvmlLauncherAPI* api, + JvmlLauncherHandle h, void* ptr, int bufferSize) { + return (*api->initJvmlLauncherData)(h, ptr, bufferSize); +} + +JvmlLauncherData* jvmLauncherCreateJvmlLauncherData(JvmlLauncherAPI* api, JvmlLauncherHandle h); +int jvmLauncherStartJvm(JvmlLauncherData* jvmArgs, void* JLI_Launch); + +void jvmLauncherLog(const char* format, ...); + +#define JP_LOG_ERRMSG(msg) do { jvmLauncherLog((msg)); } while (0) +#define JP_LOG_ERRNO JP_LOG_ERRMSG(strerror(errno)) +#define JP_LOG_TRACE jvmLauncherLog + + +#ifdef __cplusplus +} +#endif + + +#ifdef __cplusplus + #include "tstrings.h" class CfgFile; @@ -34,6 +95,9 @@ class CfgFile; class Jvm { public: + Jvm(); + ~Jvm(); + Jvm& initFromConfigFile(const CfgFile& cfgFile); Jvm& addArgument(const tstring& value) { @@ -54,9 +118,13 @@ class Jvm { void launch(); + JvmlLauncherHandle exportLauncher() const; + private: tstring jvmPath; tstring_array args; }; +#endif // #ifdef __cplusplus + #endif // JvmLauncher_h diff --git a/src/jdk.jpackage/share/native/applauncher/JvmLauncherLib.c b/src/jdk.jpackage/share/native/applauncher/JvmLauncherLib.c new file mode 100644 index 00000000000..31d4ec04b19 --- /dev/null +++ b/src/jdk.jpackage/share/native/applauncher/JvmLauncherLib.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include + +#include "JvmLauncher.h" + + +typedef int (JNICALL *JLI_LaunchFuncType)(int argc, char ** argv, + int jargc, const char** jargv, + int appclassc, const char** appclassv, + const char* fullversion, + const char* dotversion, + const char* pname, + const char* lname, + jboolean javaargs, + jboolean cpwildcard, + jboolean javaw, + jint ergo); + + +JvmlLauncherData* jvmLauncherCreateJvmlLauncherData( + JvmlLauncherAPI* api, JvmlLauncherHandle h) { + JvmlLauncherData* result = 0; + void* buf = 0; + int jvmLauncherDataBufferSize; + + if (!h) { + return 0; + } + + jvmLauncherDataBufferSize = jvmLauncherGetJvmlLauncherDataSize(api, h); + if (jvmLauncherDataBufferSize <= 0) { + goto cleanup; + } + + buf = malloc(jvmLauncherDataBufferSize); + if (!buf) { + JP_LOG_ERRNO; + goto cleanup; + } + + result = jvmLauncherInitJvmlLauncherData(api, h, buf, + jvmLauncherDataBufferSize); + if (result) { + /* Don't free the buffer in clean up. */ + buf = 0; + } + +cleanup: + jvmLauncherCloseHandle(api, h); + free(buf); + + return result; +} + + +static void dumpJvmlLauncherData(const JvmlLauncherData* jvmArgs) { + int i = 0; + JP_LOG_TRACE("jli lib: [%s]", jvmArgs->jliLibPath); + for (i = 0; i < jvmArgs->jliLaunchArgc; ++i) { + JP_LOG_TRACE("jli arg[%d]: [%s]", i, jvmArgs->jliLaunchArgv[i]); + } +} + + +int jvmLauncherStartJvm(JvmlLauncherData* jvmArgs, void* JLI_Launch) { + int exitCode; + + dumpJvmlLauncherData(jvmArgs); + exitCode = (*((JLI_LaunchFuncType)JLI_Launch))( + jvmArgs->jliLaunchArgc, jvmArgs->jliLaunchArgv, + 0, 0, + 0, 0, + "", + "", + "java", + "java", + JNI_FALSE, + JNI_FALSE, + JNI_FALSE, + 0); + + return exitCode; +} + + +void jvmLauncherLog(const char* format, ...) { + const char *withLog = getenv("JPACKAGE_DEBUG"); + if (!withLog || strcmp(withLog, "true")) { + return; + } + + va_list args; + va_start(args, format); + +#if defined(__GNUC__) && __GNUC__ >= 5 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#endif + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); +#if defined(__GNUC__) && __GNUC__ >= 5 +#pragma GCC diagnostic pop +#endif + + va_end (args); +} diff --git a/src/jdk.jpackage/share/native/common/FileUtils.cpp b/src/jdk.jpackage/share/native/common/FileUtils.cpp index 07a19ed8887..59bbd83fe7d 100644 --- a/src/jdk.jpackage/share/native/common/FileUtils.cpp +++ b/src/jdk.jpackage/share/native/common/FileUtils.cpp @@ -28,7 +28,6 @@ #include "FileUtils.h" - namespace FileUtils { #ifdef _WIN32 @@ -54,7 +53,15 @@ bool isDirSeparator(const tstring::value_type c) { tstring dirname(const tstring &path) { - tstring::size_type pos = path.find_last_of(_T("\\/")); + tstring::size_type pos; + if (tstrings::endsWith(path, _T("/.")) || tstrings::endsWith(path, _T("\\."))) { + // this method is really getparent dirname - if the path ends with "/.", + // we need to ignore that when looking for the last "/" to find parent + pos = (path.substr(0, path.length() - 2)).find_last_of(_T("\\/")); + } else { + pos = path.find_last_of(_T("\\/")); + } + if (pos != tstring::npos) { pos = path.find_last_not_of(_T("\\/"), pos); // skip trailing slashes } diff --git a/src/jdk.jpackage/share/native/common/app.cpp b/src/jdk.jpackage/share/native/common/app.cpp index ad0860d30ec..4ee7b90c256 100644 --- a/src/jdk.jpackage/share/native/common/app.cpp +++ b/src/jdk.jpackage/share/native/common/app.cpp @@ -23,6 +23,8 @@ * questions. */ +#include "kludge_c++11.h" + #include #include "app.h" #include "Log.h" @@ -56,6 +58,8 @@ class LastErrorLogAppender : public LogAppender { class ResetLastErrorMsgAtEndOfScope { public: + ResetLastErrorMsgAtEndOfScope() { + } ~ResetLastErrorMsgAtEndOfScope() { JP_NO_THROW(theLastErrorMsg = 0); } diff --git a/src/jdk.jpackage/share/native/common/tstrings.cpp b/src/jdk.jpackage/share/native/common/tstrings.cpp index d8a7e95ed98..b89d1a72c66 100644 --- a/src/jdk.jpackage/share/native/common/tstrings.cpp +++ b/src/jdk.jpackage/share/native/common/tstrings.cpp @@ -52,13 +52,13 @@ tstring unsafe_format(tstring::const_pointer format, ...) { #ifdef _MSC_VER ret = _vsntprintf_s(&*fmtout.begin(), fmtout.size(), _TRUNCATE, format, args); #else -#ifdef __GNUC__ +#if defined(__GNUC__) && __GNUC__ >= 5 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" #endif // With g++ this compiles only with '-std=gnu++0x' option ret = vsnprintf(&*fmtout.begin(), fmtout.size(), format, args); -#ifdef __GNUC__ +#if defined(__GNUC__) && __GNUC__ >= 5 #pragma GCC diagnostic pop #endif #endif @@ -207,35 +207,33 @@ namespace { */ std::string toMultiByte(const std::wstring& utf16str, int encoding) { std::string reply; - do { - int cm = WideCharToMultiByte(encoding, - 0, - utf16str.c_str(), - int(utf16str.size()), - NULL, - 0, - NULL, - NULL); - if (cm < 0) { - JP_THROW("Unexpected reply from WideCharToMultiByte()"); - } - if (0 == cm) { - break; - } + int cm = WideCharToMultiByte(encoding, + 0, + utf16str.c_str(), + int(utf16str.size()), + NULL, + 0, + NULL, + NULL); + if (cm < 0) { + JP_THROW("Unexpected reply from WideCharToMultiByte()"); + } + if (0 == cm) { + return reply; + } - reply.resize(cm); - int cm2 = WideCharToMultiByte(encoding, - 0, - utf16str.c_str(), - int(utf16str.size()), - &*reply.begin(), - cm, - NULL, - NULL); - if (cm != cm2) { - JP_THROW("Unexpected reply from WideCharToMultiByte()"); - } - } while(0); + reply.resize(cm); + int cm2 = WideCharToMultiByte(encoding, + 0, + utf16str.c_str(), + int(utf16str.size()), + &*reply.begin(), + cm, + NULL, + NULL); + if (cm != cm2) { + JP_THROW("Unexpected reply from WideCharToMultiByte()"); + } return reply; } @@ -245,31 +243,29 @@ std::string toMultiByte(const std::wstring& utf16str, int encoding) { */ std::wstring fromMultiByte(const std::string& str, int encoding) { std::wstring utf16; - do { - int cw = MultiByteToWideChar(encoding, - MB_ERR_INVALID_CHARS, - str.c_str(), - int(str.size()), - NULL, - 0); - if (cw < 0) { - JP_THROW("Unexpected reply from MultiByteToWideChar()"); - } - if (0 == cw) { - break; - } + int cw = MultiByteToWideChar(encoding, + MB_ERR_INVALID_CHARS, + str.c_str(), + int(str.size()), + NULL, + 0); + if (cw < 0) { + JP_THROW("Unexpected reply from MultiByteToWideChar()"); + } + if (0 == cw) { + return utf16; + } - utf16.resize(cw); - int cw2 = MultiByteToWideChar(encoding, - MB_ERR_INVALID_CHARS, - str.c_str(), - int(str.size()), - &*utf16.begin(), - cw); - if (cw != cw2) { - JP_THROW("Unexpected reply from MultiByteToWideChar()"); - } - } while(0); + utf16.resize(cw); + int cw2 = MultiByteToWideChar(encoding, + MB_ERR_INVALID_CHARS, + str.c_str(), + int(str.size()), + &*utf16.begin(), + cw); + if (cw != cw2) { + JP_THROW("Unexpected reply from MultiByteToWideChar()"); + } return utf16; } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourcesBuilder.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourcesBuilder.java index 3f94150b9ac..6c2dd9c5773 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourcesBuilder.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourcesBuilder.java @@ -551,9 +551,6 @@ private List addRootBranch(XMLStreamWriter xml, Path path) } List componentIds = new ArrayList<>(); - while (!SYSTEM_DIRS.contains(path = path.getParent())) { - componentIds.add(addRemoveDirectoryComponent(xml, path)); - } return componentIds; } diff --git a/src/jdk.jpackage/windows/native/libjpackage/WindowsRegistry.cpp b/src/jdk.jpackage/windows/native/libjpackage/WindowsRegistry.cpp index 3ecefb1adca..931cec8f5c6 100644 --- a/src/jdk.jpackage/windows/native/libjpackage/WindowsRegistry.cpp +++ b/src/jdk.jpackage/windows/native/libjpackage/WindowsRegistry.cpp @@ -68,9 +68,9 @@ std::wstring GetLongPath(const std::wstring& path) { } // namespace -#ifdef __cplusplus + extern "C" { -#endif + #undef jdk_jpackage_internal_WindowsRegistry_HKEY_LOCAL_MACHINE #define jdk_jpackage_internal_WindowsRegistry_HKEY_LOCAL_MACHINE 1L @@ -216,6 +216,4 @@ extern "C" { return JNI_FALSE; } -#ifdef __cplusplus -} -#endif +} // extern "C" diff --git a/src/jdk.jpackage/windows/native/libjpackage/jpackage.cpp b/src/jdk.jpackage/windows/native/libjpackage/jpackage.cpp index 69a8e098d8e..b6dcb53b525 100644 --- a/src/jdk.jpackage/windows/native/libjpackage/jpackage.cpp +++ b/src/jdk.jpackage/windows/native/libjpackage/jpackage.cpp @@ -30,9 +30,7 @@ #include "JniUtils.h" #include "MsiDb.h" -#ifdef __cplusplus extern "C" { -#endif /* * Class: jdk_jpackage_internal_ExecutableRebrander @@ -159,6 +157,4 @@ extern "C" { return 1; } -#ifdef __cplusplus -} -#endif +} // extern "C" \ No newline at end of file diff --git a/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java b/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java index 926213bbe11..8ed7b6a1742 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java @@ -230,7 +230,7 @@ static enum TK { PUBLIC(TokenKind.PUBLIC, XDECL1 | XMODIFIER), // public TRANSIENT(TokenKind.TRANSIENT, XDECL1 | XMODIFIER), // transient VOLATILE(TokenKind.VOLATILE, XDECL1 | XMODIFIER), // volatile - VALUE(TokenKind.VALUE, 0), + PRIMITIVE(TokenKind.PRIMITIVE, 0), // Declarations and type parameters (thus expressions) EXTENDS(TokenKind.EXTENDS, XEXPR|XDECL), // extends diff --git a/src/jdk.jshell/share/man/jshell.1 b/src/jdk.jshell/share/man/jshell.1 index 01d6a24b30a..39d18e197ef 100644 --- a/src/jdk.jshell/share/man/jshell.1 +++ b/src/jdk.jshell/share/man/jshell.1 @@ -22,7 +22,7 @@ .\"t .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JSHELL" "1" "2020" "JDK 16" "JDK Commands" +.TH "JSHELL" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.jstatd/share/man/jstatd.1 b/src/jdk.jstatd/share/man/jstatd.1 index 88d3222c364..21388eb527a 100644 --- a/src/jdk.jstatd/share/man/jstatd.1 +++ b/src/jdk.jstatd/share/man/jstatd.1 @@ -21,7 +21,7 @@ .\" .\" Automatically generated by Pandoc 2.3.1 .\" -.TH "JSTATD" "1" "2020" "JDK 16" "JDK Commands" +.TH "JSTATD" "1" "2021" "JDK 17\-ea" "JDK Commands" .hy .SH NAME .PP diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java index 0bf2a145b23..b6408a122ca 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.time.Duration; import java.time.Instant; import java.time.LocalDateTime; @@ -40,19 +41,20 @@ import java.util.Iterator; import java.util.Objects; +import jdk.jfr.internal.management.ChunkFilename; import jdk.jfr.internal.management.ManagementSupport; final class DiskRepository implements Closeable { final static class DiskChunk { final Path path; - final Instant startTime; + final long startTimeNanos; Instant endTime; long size; DiskChunk(Path path, long startNanos) { this.path = path; - this.startTime = ManagementSupport.epochNanosToInstant(startNanos); + this.startTimeNanos = startNanos; } } @@ -80,6 +82,7 @@ public State next() { private final boolean deleteDirectory; private final ByteBuffer buffer = ByteBuffer.allocate(256); private final Path directory; + private final ChunkFilename chunkFilename; private RandomAccessFile raf; private RandomAccessFile previousRAF; @@ -103,6 +106,7 @@ public State next() { public DiskRepository(Path path, boolean deleteDirectory) throws IOException { this.directory = path; this.deleteDirectory = deleteDirectory; + this.chunkFilename = ChunkFilename.newUnpriviliged(path); } public synchronized void write(byte[] bytes) throws IOException { @@ -295,8 +299,8 @@ private void writeCheckPointHeader() throws IOException { previousRAFstate = state; currentChunk.size = Files.size(currentChunk.path); long durationNanos = buffer.getLong(HEADER_FILE_DURATION); - Duration d = Duration.ofNanos(durationNanos); - currentChunk.endTime = currentChunk.startTime.plus(d); + long endTimeNanos = currentChunk.startTimeNanos + durationNanos; + currentChunk.endTime = ManagementSupport.epochNanosToInstant(endTimeNanos); } raf.seek(position); } @@ -325,44 +329,8 @@ private DiskChunk nextChunk() throws IOException { int nanoOfSecond = (int) (nanos % 1_000_000_000); ZoneOffset z = OffsetDateTime.now().getOffset(); LocalDateTime d = LocalDateTime.ofEpochSecond(epochSecond, nanoOfSecond, z); - String filename = formatDateTime(d); - Path p1 = directory.resolve(filename + ".jfr"); - if (!Files.exists(p1)) { - return new DiskChunk(p1, nanos); - } - for (int i = 1; i < 100; i++) { - String s = Integer.toString(i); - if (i < 10) { - s = "0" + s; - } - Path p2 = directory.resolve(filename + "_" + s + ".jfr"); - if (!Files.exists(p2)) { - return new DiskChunk(p2, nanos); - } - } - throw new IOException("Could not create chunk for path " + p1); - } - - static String formatDateTime(LocalDateTime time) { - StringBuilder sb = new StringBuilder(19); - sb.append(time.getYear() / 100); - appendPadded(sb, time.getYear() % 100, true); - appendPadded(sb, time.getMonth().getValue(), true); - appendPadded(sb, time.getDayOfMonth(), true); - appendPadded(sb, time.getHour(), true); - appendPadded(sb, time.getMinute(), true); - appendPadded(sb, time.getSecond(), false); - return sb.toString(); - } - - private static void appendPadded(StringBuilder text, int number, boolean separator) { - if (number < 10) { - text.append('0'); - } - text.append(number); - if (separator) { - text.append('_'); - } + String filename = chunkFilename.next(d); + return new DiskChunk(Paths.get(filename), nanos); } @Override @@ -423,11 +391,11 @@ private void trimToAge(Instant oldest) { cleanUpDeadChunk(count + 10); } - public synchronized void onChunkComplete(Instant timestamp) { + public synchronized void onChunkComplete(long endTimeNanos) { int count = 0; while (!activeChunks.isEmpty()) { DiskChunk oldestChunk = activeChunks.peek(); - if (oldestChunk.startTime.isBefore(timestamp)) { + if (oldestChunk.startTimeNanos < endTimeNanos) { removeOldestChunk(); count++; } else { diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/DownLoadThread.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/DownLoadThread.java index 68d2fc5f6c8..5ce66692537 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/DownLoadThread.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/DownLoadThread.java @@ -29,13 +29,16 @@ import java.util.HashMap; import java.util.Map; +import jdk.jfr.internal.management.ManagementSupport; + final class DownLoadThread extends Thread { private final RemoteRecordingStream stream; private final Instant startTime; private final Instant endTime; private final DiskRepository diskRepository; - DownLoadThread(RemoteRecordingStream stream) { + DownLoadThread(RemoteRecordingStream stream, String name) { + super(name); this.stream = stream; this.startTime = stream.startTime; this.endTime = stream.endTime; @@ -65,7 +68,7 @@ public void run() { } } } catch (IOException ioe) { - // ignore + ManagementSupport.logDebug(ioe.getMessage()); } finally { diskRepository.complete(); } diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java index c5af59d1776..c35a66b7913 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/RemoteRecordingStream.java @@ -133,8 +133,7 @@ final static class ChunkConsumer implements Consumer { @Override public void accept(Long endNanos) { - Instant t = ManagementSupport.epochNanosToInstant(endNanos); - repository.onChunkComplete(t); + repository.onChunkComplete(endNanos); } } @@ -552,8 +551,8 @@ private static Path makeTempDirectory() throws IOException { } private void startDownload() { - Thread downLoadThread = new DownLoadThread(this); - downLoadThread.setName("JFR: Download Thread " + creationTime); + String name = "JFR: Download Thread " + creationTime; + Thread downLoadThread = new DownLoadThread(this, name); downLoadThread.start(); } diff --git a/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c b/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c index ddb58e288d6..350a0d0edb6 100644 --- a/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c +++ b/src/jdk.sctp/unix/native/libsctp/SctpChannelImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -475,6 +475,7 @@ JNIEXPORT jint JNICALL Java_sun_nio_ch_sctp_SctpChannelImpl_receive0 iov->iov_len = SCTP_NOTIFICATION_SIZE - rv; if ((rv = recvmsg(fd, msg, flags)) < 0) { handleSocketError(env, errno); + free(newBuf); return 0; } bufp = newBuf; diff --git a/src/utils/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ConnectionFilter.java b/src/utils/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ConnectionFilter.java index 6a77ba6e078..d1c9bd69258 100644 --- a/src/utils/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ConnectionFilter.java +++ b/src/utils/IdealGraphVisualizer/Filter/src/com/sun/hotspot/igv/filter/ConnectionFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,10 +63,8 @@ public void apply(Diagram diagram) { for (Figure f : figures) { for (OutputSlot os : f.getOutputSlots()) { for (Connection c : os.getConnections()) { - if (figures.contains(c.getInputSlot().getFigure())) { - c.setStyle(rule.getLineStyle()); - c.setColor(rule.getLineColor()); - } + c.setStyle(rule.getLineStyle()); + c.setColor(rule.getLineColor()); } } } diff --git a/src/utils/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/layer.xml b/src/utils/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/layer.xml index 714e4884007..1728e5b940c 100644 --- a/src/utils/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/layer.xml +++ b/src/utils/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/layer.xml @@ -2,33 +2,5 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/utils/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java b/src/utils/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java index 3a7498f74c1..c2a69f2efa8 100644 --- a/src/utils/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java +++ b/src/utils/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Connection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,8 @@ public enum ConnectionStyle { NORMAL, DASHED, - BOLD + BOLD, + INVISIBLE } private InputSlot inputSlot; private OutputSlot outputSlot; diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/color.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/color.filter index dfaf7f3c1ac..a0e063a0c1b 100644 --- a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/color.filter +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/color.filter @@ -1,18 +1,25 @@ -colorize("name", ".*", yellow); -colorize("name", "Catch.*", blue); -colorize("name", "Region|Loop|CountedLoop|Root", red); -colorize("name", "CProj|IfFalse|IfTrue|JProj|CatchProj", magenta); -colorize("name", "Con.*", orange); -colorize("name", "Parm|Proj", lightGray); +var mixedNodeColor = java.awt.Color.decode("#ffaabb"); +var controlNodeColor = java.awt.Color.decode("#ee8866"); +var otherNodeColor = java.awt.Color.decode("#eedd88"); +var dataNodeColor = java.awt.Color.decode("#adcbea"); +var memoryNodeColor = java.awt.Color.decode("#babb00"); -// Nodes with bci -colorize("bci", "..*", magenta); +var mixedEdgeColor = java.awt.Color.decode("#ff7f99"); +var controlEdgeColor = java.awt.Color.decode("#e75828"); +var otherEdgeColor = java.awt.Color.decode("#dfc025"); +var dataEdgeColor = java.awt.Color.decode("#3178c2"); +var memoryEdgeColor = java.awt.Color.decode("#828200"); + +colorize("category", "data", dataNodeColor); +colorize("category", "memory", memoryNodeColor); +colorize("category", "mixed", mixedNodeColor); +colorize("category", "control", controlNodeColor); +colorize("category", "other", otherNodeColor); -// Line style var f = new ColorFilter("Line Style filter"); -f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "int:")), null, Color.BLUE, null)); -f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "control")), null, Color.RED, null)); -f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "memory")), null, Color.GREEN, null)); -f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "tuple:")), null, Color.MAGENTA, null)); -f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("type", "bottom")), null, Color.LIGHT_GRAY, null)); +f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "data")), null, dataEdgeColor, null)); +f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "memory")), null, memoryEdgeColor, null)); +f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "mixed")), null, mixedEdgeColor, null)); +f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "control")), null, controlEdgeColor, null)); +f.addRule(new ColorFilter.ColorRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "other")), null, otherEdgeColor, null)); f.apply(graph); \ No newline at end of file diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/colorFrequency.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/colorFrequency.filter new file mode 100644 index 00000000000..13fad66cd65 --- /dev/null +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/colorFrequency.filter @@ -0,0 +1,23 @@ +// Color nodes by estimated execution frequency. Applies only when control-flow +// graph information is available (from "Global Code Motion" on). + +// These colors are generated by running: +// $ python3 extract-colors.py --steps 10 --colormap coolwarm +var step0Color = java.awt.Color.decode("#3b4cc0"); +var step1Color = java.awt.Color.decode("#5977e3"); +var step2Color = java.awt.Color.decode("#7b9ff9"); +var step3Color = java.awt.Color.decode("#9ebeff"); +var step4Color = java.awt.Color.decode("#c0d4f5"); +var step5Color = java.awt.Color.decode("#dddcdc"); +var step6Color = java.awt.Color.decode("#f2cbb7"); +var step7Color = java.awt.Color.decode("#f7ac8e"); +var step8Color = java.awt.Color.decode("#ee8468"); +var step9Color = java.awt.Color.decode("#d65244"); +var step10Color = java.awt.Color.decode("#b40426"); + +var colors = [step0Color, step1Color, step2Color, step3Color, step4Color, step5Color, step6Color, step7Color, step8Color, step9Color, step10Color] +var fractions = [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] + +// The max value is set to 1.01 instead of 1.0 to workaround a (numerical?) +// issue where nodes with frequencies close (but not equal to) 1.0 are not colored. +colorizeGradientCustom("frequency", 0.0, 1.01, "logarithmic", colors, fractions, 1024); \ No newline at end of file diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/extract-colors.py b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/extract-colors.py new file mode 100644 index 00000000000..1d5239d1163 --- /dev/null +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/extract-colors.py @@ -0,0 +1,41 @@ +#!/usr/bin/python3 +# +# Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +import matplotlib.cm +import argparse +import sys + +parser = argparse.ArgumentParser() +parser.add_argument('--steps', type=int, default=10) +parser.add_argument('--colormap', default='coolwarm') +args = parser.parse_args() + +cmap = matplotlib.cm.get_cmap(args.colormap) +n = args.steps + +for step in range(n + 1): + point = step / float(n) + rgb = tuple([int(round(c * 255)) for c in cmap(point)[0:3]]) + hex = '#%02x%02x%02x' % rgb + print("var step" + str(step) + "Color" + " = java.awt.Color.decode(\"" + \ + hex + "\");") diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideControl.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideControl.filter new file mode 100644 index 00000000000..f3c28c2e84d --- /dev/null +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideControl.filter @@ -0,0 +1,3 @@ +var f = new RemoveFilter("Hide control subgraph"); +f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "control")))); +f.apply(graph); diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideControlEdges.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideControlEdges.filter new file mode 100644 index 00000000000..f5f072156bf --- /dev/null +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideControlEdges.filter @@ -0,0 +1,5 @@ +var f = new ConnectionFilter("Hide control edges"); +f.addRule(new ConnectionFilter.ConnectionStyleRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "control")), + white, + Connection.ConnectionStyle.INVISIBLE)); +f.apply(graph); diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideData.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideData.filter new file mode 100644 index 00000000000..0e1359f9908 --- /dev/null +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideData.filter @@ -0,0 +1,3 @@ +var f = new RemoveFilter("Hide data subgraph"); +f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "data")))); +f.apply(graph); diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideDataEdges.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideDataEdges.filter new file mode 100644 index 00000000000..59842237ced --- /dev/null +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideDataEdges.filter @@ -0,0 +1,5 @@ +var f = new ConnectionFilter("Hide data edges"); +f.addRule(new ConnectionFilter.ConnectionStyleRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "data")), + white, + Connection.ConnectionStyle.INVISIBLE)); +f.apply(graph); diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideMemory.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideMemory.filter new file mode 100644 index 00000000000..d85e050bf4c --- /dev/null +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideMemory.filter @@ -0,0 +1,3 @@ +var f = new RemoveFilter("Hide memory subgraph"); +f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "memory")))); +f.apply(graph); diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideMemoryEdges.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideMemoryEdges.filter new file mode 100644 index 00000000000..360533e74b8 --- /dev/null +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideMemoryEdges.filter @@ -0,0 +1,5 @@ +var f = new ConnectionFilter("Hide memory edges"); +f.addRule(new ConnectionFilter.ConnectionStyleRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "memory")), + white, + Connection.ConnectionStyle.INVISIBLE)); +f.apply(graph); diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideMixed.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideMixed.filter new file mode 100644 index 00000000000..a0693aeabf9 --- /dev/null +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideMixed.filter @@ -0,0 +1,3 @@ +var f = new RemoveFilter("Hide mixed subgraph"); +f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "mixed")))); +f.apply(graph); diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideMixedEdges.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideMixedEdges.filter new file mode 100644 index 00000000000..7e367d48019 --- /dev/null +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideMixedEdges.filter @@ -0,0 +1,5 @@ +var f = new ConnectionFilter("Hide mixed edges"); +f.addRule(new ConnectionFilter.ConnectionStyleRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "mixed")), + white, + Connection.ConnectionStyle.INVISIBLE)); +f.apply(graph); diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideOther.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideOther.filter new file mode 100644 index 00000000000..f345d2781a1 --- /dev/null +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideOther.filter @@ -0,0 +1,3 @@ +var f = new RemoveFilter("Hide other subgraph"); +f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "other")))); +f.apply(graph); diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideOtherEdges.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideOtherEdges.filter new file mode 100644 index 00000000000..bf6f7e86c5e --- /dev/null +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/hideOtherEdges.filter @@ -0,0 +1,5 @@ +var f = new ConnectionFilter("Hide other edges"); +f.addRule(new ConnectionFilter.ConnectionStyleRule(new MatcherSelector(new Properties.StringPropertyMatcher("category", "other")), + white, + Connection.ConnectionStyle.INVISIBLE)); +f.apply(graph); diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/onlyControlFlow.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/onlyControlFlow.filter index 73c1f8ab615..b73668e9490 100644 --- a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/onlyControlFlow.filter +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/onlyControlFlow.filter @@ -1,24 +1,27 @@ +// Remove all nodes except control, mixed, and nodes of 'bottom' type that are +// successors of control nodes (typically 'Halt', 'Return', etc.). + var f = new RemoveFilter("Show only control flow"); f.addRule( new RemoveFilter.RemoveRule( new InvertSelector( new OrSelector( - new OrSelector( + new MatcherSelector( + new Properties.RegexpPropertyMatcher("category", "control|mixed") + ), + new AndSelector( new SuccessorSelector( new MatcherSelector( - new Properties.StringPropertyMatcher("type", "control") + new Properties.RegexpPropertyMatcher("type", "control") ) ), - new MatcherSelector( - new Properties.StringPropertyMatcher("type", "control") + new MatcherSelector( + new Properties.RegexpPropertyMatcher("type", "bottom") ) - ), - new MatcherSelector( - new Properties.StringPropertyMatcher("name", "Start") ) ) - ), false + ), + false ) ); -f.addRule(new RemoveFilter.RemoveRule(new MatcherSelector(new Properties.RegexpPropertyMatcher("name", "Phi|Store.")))); f.apply(graph); \ No newline at end of file diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/remove.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/remove.filter deleted file mode 100644 index 9a051a89e60..00000000000 --- a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/remove.filter +++ /dev/null @@ -1,8 +0,0 @@ -remove("dump_spec", "FramePtr|ReturnAdr|I_O"); -removeInputs("name", "Root"); -var f = new RemoveSelfLoopsFilter("Remove Self-Loops"); -f.apply(graph); -removeInputs("name", "SafePoint|CallStaticJava|CallDynamicJava|CallJava|CallLeaf|CallRuntime|AbstractLock|CallLeafNoFP|Call|CallStaticJavaDirect", 5); -removeInputs("name", "Unlock|Lock", 7); -removeInputs("name", "Allocate", 7); -removeInputs("name", "AllocateArray", 9); \ No newline at end of file diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/structural.filter b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/structural.filter index 3e59fbc1d2a..34d91b9f7da 100644 --- a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/structural.filter +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/filters/structural.filter @@ -1,6 +1,19 @@ +// Hide secondary edges. +remove("dump_spec", "FramePtr|ReturnAdr|I_O"); +removeInputs("name", "Root"); +var f = new RemoveSelfLoopsFilter("Remove Self-Loops"); +f.apply(graph); +removeInputs("name", "SafePoint|CallStaticJava|CallDynamicJava|CallJava|CallLeaf|CallRuntime|AbstractLock|CallLeafNoFP|Call|CallStaticJavaDirect", 5); +removeInputs("name", "Unlock|Lock", 7); +removeInputs("name", "Allocate", 7); +removeInputs("name", "AllocateArray", 9); + +// Combine projection nodes. var f = new CombineFilter("Combine Filter"); f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", ".*"), new Properties.RegexpPropertyMatcher("name", "Proj|IfFalse|IfTrue|JProj|MachProj|JumpProj|CatchProj"))); f.addRule(new CombineFilter.CombineRule(new Properties.RegexpPropertyMatcher("name", "Cmp.*"), new Properties.RegexpPropertyMatcher("name", "Bool"))); f.apply(graph); + +// Inline (split) constant nodes. split("name", "BoxLock"); split("name", "(Con.*)|(loadCon.*)", "[dump_spec]"); \ No newline at end of file diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/layer.xml b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/layer.xml index de53ba060ea..6ad622863e3 100644 --- a/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/layer.xml +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/com/sun/hotspot/igv/servercompiler/layer.xml @@ -2,28 +2,60 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + diff --git a/src/utils/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java b/src/utils/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java index f30003fdcdc..7efafe7a748 100644 --- a/src/utils/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java +++ b/src/utils/IdealGraphVisualizer/View/src/com/sun/hotspot/igv/view/DiagramScene.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -779,6 +779,7 @@ private void processOutputSlot(Set> lastLineCache, OutputSlot boolean isBold = false; boolean isDashed = true; + boolean isVisible = true; for (Connection c : connectionList) { @@ -789,6 +790,10 @@ private void processOutputSlot(Set> lastLineCache, OutputSlot if (c.getStyle() != Connection.ConnectionStyle.DASHED) { isDashed = false; } + + if (c.getStyle() == Connection.ConnectionStyle.INVISIBLE) { + isVisible = false; + } } LineWidget newPredecessor = predecessor; @@ -804,6 +809,7 @@ private void processOutputSlot(Set> lastLineCache, OutputSlot curAnimator = null; } LineWidget w = new LineWidget(this, s, connectionList, p1, p2, predecessor, curAnimator, isBold, isDashed); + w.setVisible(isVisible); lineCache.add(curPair); newPredecessor = w; diff --git a/test/hotspot/gtest/gc/shared/test_oopStorage_parperf.cpp b/test/hotspot/gtest/gc/shared/test_oopStorage_parperf.cpp index dea8fe7903a..31d0c4fcc80 100644 --- a/test/hotspot/gtest/gc/shared/test_oopStorage_parperf.cpp +++ b/test/hotspot/gtest/gc/shared/test_oopStorage_parperf.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ #include "runtime/vmOperations.hpp" #include "runtime/vmThread.hpp" #include "utilities/debug.hpp" +#include "utilities/formatBuffer.hpp" #include "utilities/ostream.hpp" #include "utilities/ticks.hpp" diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 01987717223..862c5c8225a 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -162,6 +162,7 @@ gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293 macosx-x64 runtime/cds/appcds/jigsaw/modulepath/ModulePathAndCP_JFR.java 8253437 windows-x64 runtime/cds/DeterministicDump.java 8253495 generic-all runtime/jni/terminatedThread/TestTerminatedThread.java 8219652 aix-ppc64 +runtime/NMT/CheckForProperDetailStackTrace.java 8261520 generic-all runtime/ReservedStack/ReservedStackTest.java 8231031 generic-all containers/docker/TestJFRWithJMX.java 8256417 linux-5.4.17-2011.5.3.el8uek.x86_64 @@ -197,7 +198,6 @@ serviceability/sa/TestRevPtrsForInvokeDynamic.java 8241235 generic-all serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorStatIntervalTest.java 8214032 generic-all serviceability/jvmti/HeapMonitor/MyPackage/HeapMonitorStatArrayCorrectnessTest.java 8224150 generic-all serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java 8225354 windows-all -serviceability/attach/RemovingUnixDomainSocketTest.java 8248162 linux-x64 # Valhalla TODO: serviceability/sa/ClhsdbCDSCore.java 8190936 generic-all diff --git a/test/hotspot/jtreg/compiler/c2/TestShiftRightAndAccumulate.java b/test/hotspot/jtreg/compiler/c2/TestShiftRightAndAccumulate.java new file mode 100644 index 00000000000..517bed22b14 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestShiftRightAndAccumulate.java @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8260585 + * @summary AArch64: Wrong code generated for shifting right and accumulating four unsigned short integers. + * @run main/othervm compiler.c2.TestShiftRightAndAccumulate + * @run main/othervm -Xcomp compiler.c2.TestShiftRightAndAccumulate + * @run main/othervm -XX:-SuperWordLoopUnrollAnalysis compiler.c2.TestShiftRightAndAccumulate + */ + +package compiler.c2; + +import java.util.Random; +import java.util.Arrays; + +public class TestShiftRightAndAccumulate { + private static final int SMALL_LEN = 16; + private static final int LARGE_LEN = 1000; + private static final int NUM_ITERS = 200000; + private static final int MAX_TESTS = 10; + private static final int SMALL_INTS_LEN = 3; + private static final int SMALL_BYTES_LEN = 80; + + private static byte[] bytesA, bytesB, bytesC, bytesD; + private static short[] shortsA, shortsB, shortsC, shortsD; + private static char[] charsA, charsB, charsC; + private static int[] intsA, intsB, intsC; + private static long[] longsA, longsB, longsC; + + private static byte gBytes[][]; + private static short gShorts[][]; + private static char gChars[][]; + private static int gInts[][]; + private static long gLongs[][]; + + private static Random r = new Random(32781); + + public static void main(String args[]) { + test_init(SMALL_LEN); + for (int it = 0; it < NUM_ITERS; it++) { + test_bytes(); + test_shorts(); + test_chars(); + test_ints(); + test_longs(); + } + + test_init(LARGE_LEN); + for (int it = 0; it < NUM_ITERS; it++) { + test_bytes(); + test_shorts(); + test_chars(); + test_ints(); + test_longs(); + } + System.out.println("Test PASSED"); + } + + static void test_bytes() { + for (int i = 0; i < bytesC.length; i++) { + bytesC[i] = (byte) (bytesA[i] + (bytesB[i] >> 1)); + bytesD[i] = (byte) (bytesA[i] + bytesB[i]); + } + assertTrue(Arrays.equals(bytesC, gBytes[0])); + assertTrue(Arrays.equals(bytesD, gBytes[MAX_TESTS])); + + for (int i = 0; i < bytesC.length; i++) { + bytesC[i] = (byte) (bytesA[i] + (bytesB[i] >> 8)); + bytesD[i] = (byte) (bytesA[i] + bytesB[i]); + } + assertTrue(Arrays.equals(bytesC, gBytes[1])); + assertTrue(Arrays.equals(bytesD, gBytes[MAX_TESTS + 1])); + + for (int i = 0; i < bytesC.length; i++) { + bytesC[i] = (byte) (bytesA[i] + (bytesB[i] >> 13)); + bytesD[i] = (byte) (bytesA[i] + bytesB[i]); + } + assertTrue(Arrays.equals(bytesC, gBytes[2])); + assertTrue(Arrays.equals(bytesD, gBytes[MAX_TESTS + 2])); + + for (int i = 0; i < bytesC.length; i++) { + bytesC[i] = (byte) (bytesA[i] + (bytesB[i] >> 19)); + bytesD[i] = (byte) (bytesA[i] + bytesB[i]); + } + assertTrue(Arrays.equals(bytesC, gBytes[3])); + assertTrue(Arrays.equals(bytesD, gBytes[MAX_TESTS + 3])); + + for (int i = 0; i < bytesC.length; i++) { + bytesC[i] = (byte) (bytesA[i] + (bytesB[i] >>> 1)); + bytesD[i] = (byte) (bytesA[i] + bytesB[i]); + } + assertTrue(Arrays.equals(bytesC, gBytes[4])); + assertTrue(Arrays.equals(bytesD, gBytes[MAX_TESTS + 4])); + + for (int i = 0; i < bytesC.length; i++) { + bytesC[i] = (byte) (bytesA[i] + (bytesB[i] >>> 8)); + bytesD[i] = (byte) (bytesA[i] + bytesB[i]); + } + assertTrue(Arrays.equals(bytesC, gBytes[5])); + assertTrue(Arrays.equals(bytesD, gBytes[MAX_TESTS + 5])); + + for (int i = 0; i < bytesC.length; i++) { + bytesC[i] = (byte) (bytesA[i] + (bytesB[i] >>> 13)); + bytesD[i] = (byte) (bytesA[i] + bytesB[i]); + } + assertTrue(Arrays.equals(bytesC, gBytes[6])); + assertTrue(Arrays.equals(bytesD, gBytes[MAX_TESTS + 6])); + + for (int i = 0; i < bytesC.length; i++) { + bytesC[i] = (byte) (bytesA[i] + (bytesB[i] >>> 19)); + bytesD[i] = (byte) (bytesA[i] + bytesB[i]); + } + assertTrue(Arrays.equals(bytesC, gBytes[7])); + assertTrue(Arrays.equals(bytesD, gBytes[MAX_TESTS + 7])); + } + + static void test_shorts() { + for (int i = 0; i < shortsC.length; i++) { + shortsC[i] = (short) (shortsA[i] + (shortsB[i] >> 5)); + shortsD[i] = (short) (shortsA[i] + shortsB[i]); + } + assertTrue(Arrays.equals(shortsC, gShorts[0])); + assertTrue(Arrays.equals(shortsD, gShorts[MAX_TESTS])); + + for (int i = 0; i < shortsC.length; i++) { + shortsC[i] = (short) (shortsA[i] + (shortsB[i] >> 16)); + shortsD[i] = (short) (shortsA[i] + shortsB[i]); + } + assertTrue(Arrays.equals(shortsC, gShorts[1])); + assertTrue(Arrays.equals(shortsD, gShorts[MAX_TESTS + 1])); + + for (int i = 0; i < shortsC.length; i++) { + shortsC[i] = (short) (shortsA[i] + (shortsB[i] >> 23)); + shortsD[i] = (short) (shortsA[i] + shortsB[i]); + } + assertTrue(Arrays.equals(shortsC, gShorts[2])); + assertTrue(Arrays.equals(shortsD, gShorts[MAX_TESTS + 2])); + + for (int i = 0; i < shortsC.length; i++) { + shortsC[i] = (short) (shortsA[i] + (shortsB[i] >> 35)); + shortsD[i] = (short) (shortsA[i] + shortsB[i]); + } + assertTrue(Arrays.equals(shortsC, gShorts[3])); + assertTrue(Arrays.equals(shortsD, gShorts[MAX_TESTS + 3])); + + for (int i = 0; i < shortsC.length; i++) { + shortsC[i] = (short) (shortsA[i] + (shortsB[i] >>> 7)); + shortsD[i] = (short) (shortsA[i] + shortsB[i]); + } + assertTrue(Arrays.equals(shortsC, gShorts[4])); + assertTrue(Arrays.equals(shortsD, gShorts[MAX_TESTS + 4])); + + for (int i = 0; i < shortsC.length; i++) { + shortsC[i] = (short) (shortsA[i] + (shortsB[i] >>> 16)); + shortsD[i] = (short) (shortsA[i] + shortsB[i]); + } + assertTrue(Arrays.equals(shortsC, gShorts[5])); + assertTrue(Arrays.equals(shortsD, gShorts[MAX_TESTS + 5])); + + for (int i = 0; i < shortsC.length; i++) { + shortsC[i] = (short) (shortsA[i] + (shortsB[i] >>> 23)); + shortsD[i] = (short) (shortsA[i] + shortsB[i]); + } + assertTrue(Arrays.equals(shortsC, gShorts[6])); + assertTrue(Arrays.equals(shortsD, gShorts[MAX_TESTS + 6])); + + for (int i = 0; i < shortsC.length; i++) { + shortsC[i] = (short) (shortsA[i] + (shortsB[i] >>> 35)); + shortsD[i] = (short) (shortsA[i] + shortsB[i]); + } + assertTrue(Arrays.equals(shortsC, gShorts[7])); + assertTrue(Arrays.equals(shortsD, gShorts[MAX_TESTS + 7])); + } + + static void test_chars() { + for (int i = 0; i < charsC.length; i++) { + charsC[i] = (char) (charsA[i] + (charsB[i] >>> 4)); + charsC[i] = (char) (charsC[i] + charsA[i] + charsB[i]); + } + assertTrue(Arrays.equals(charsC, gChars[0])); + + for (int i = 0; i < charsC.length; i++) { + charsC[i] = (char) (charsA[i] + (charsB[i] >>> 16)); + charsC[i] = (char) (charsC[i] + charsA[i] + charsB[i]); + } + assertTrue(Arrays.equals(charsC, gChars[1])); + + for (int i = 0; i < charsC.length; i++) { + charsC[i] = (char) (charsA[i] + (charsB[i] >>> 19)); + charsC[i] = (char) (charsC[i] + charsA[i] + charsB[i]); + } + assertTrue(Arrays.equals(charsC, gChars[2])); + + for (int i = 0; i < charsC.length; i++) { + charsC[i] = (char) (charsA[i] + (charsB[i] >>> 35)); + charsC[i] = (char) (charsC[i] + charsA[i] + charsB[i]); + } + assertTrue(Arrays.equals(charsC, gChars[3])); + } + + static void test_ints() { + for (int i = 0; i < intsC.length; i++) { + intsC[i] = (intsA[i] + (intsB[i] >> 19)); + intsC[i] = (intsC[i] + intsA[i] + intsB[i]); + } + assertTrue(Arrays.equals(intsC, gInts[0])); + + for (int i = 0; i < intsC.length; i++) { + intsC[i] = (intsA[i] + (intsB[i] >> 32)); + intsC[i] = (intsC[i] + intsA[i] + intsB[i]); + } + assertTrue(Arrays.equals(intsC, gInts[1])); + + for (int i = 0; i < intsC.length; i++) { + intsC[i] = (intsA[i] + (intsB[i] >> 49)); + intsC[i] = (intsC[i] + intsA[i] + intsB[i]); + } + assertTrue(Arrays.equals(intsC, gInts[2])); + + for (int i = 0; i < intsC.length; i++) { + intsC[i] = (intsA[i] + (intsB[i] >> 67)); + intsC[i] = (intsC[i] + intsA[i] + intsB[i]); + } + assertTrue(Arrays.equals(intsC, gInts[3])); + + for (int i = 0; i < intsC.length; i++) { + intsC[i] = (intsA[i] + (intsB[i] >>> 19)); + intsC[i] = (intsC[i] + intsA[i] + intsB[i]); + } + assertTrue(Arrays.equals(intsC, gInts[4])); + + for (int i = 0; i < intsC.length; i++) { + intsC[i] = (intsA[i] + (intsB[i] >>> 32)); + intsC[i] = (intsC[i] + intsA[i] + intsB[i]); + } + assertTrue(Arrays.equals(intsC, gInts[5])); + + for (int i = 0; i < intsC.length; i++) { + intsC[i] = (intsA[i] + (intsB[i] >>> 49)); + intsC[i] = (intsC[i] + intsA[i] + intsB[i]); + } + assertTrue(Arrays.equals(intsC, gInts[6])); + + for (int i = 0; i < intsC.length; i++) { + intsC[i] = (intsA[i] + (intsB[i] >>> 67)); + intsC[i] = (intsC[i] + intsA[i] + intsB[i]); + } + assertTrue(Arrays.equals(intsC, gInts[7])); + } + + static void test_longs() { + for (int i = 0; i < longsC.length; i++) { + longsC[i] = (longsA[i] + (longsB[i] >> 37)); + longsC[i] = (longsC[i] + longsA[i] + longsB[i]); + } + assertTrue(Arrays.equals(longsC, gLongs[0])); + + for (int i = 0; i < longsC.length; i++) { + longsC[i] = (longsA[i] + (longsB[i] >> 64)); + longsC[i] = (longsC[i] + longsA[i] + longsB[i]); + } + assertTrue(Arrays.equals(longsC, gLongs[1])); + + for (int i = 0; i < longsC.length; i++) { + longsC[i] = (longsA[i] + (longsB[i] >> 93)); + longsC[i] = (longsC[i] + longsA[i] + longsB[i]); + } + assertTrue(Arrays.equals(longsC, gLongs[2])); + + for (int i = 0; i < longsC.length; i++) { + longsC[i] = (longsA[i] + (longsB[i] >> 137)); + longsC[i] = (longsC[i] + longsA[i] + longsB[i]); + } + assertTrue(Arrays.equals(longsC, gLongs[3])); + + for (int i = 0; i < longsC.length; i++) { + longsC[i] = (longsA[i] + (longsB[i] >>> 37)); + longsC[i] = (longsC[i] + longsA[i] + longsB[i]); + } + assertTrue(Arrays.equals(longsC, gLongs[4])); + + for (int i = 0; i < longsC.length; i++) { + longsC[i] = (longsA[i] + (longsB[i] >>> 64)); + longsC[i] = (longsC[i] + longsA[i] + longsB[i]); + } + assertTrue(Arrays.equals(longsC, gLongs[5])); + + for (int i = 0; i < longsC.length; i++) { + longsC[i] = (longsA[i] + (longsB[i] >>> 93)); + longsC[i] = (longsC[i] + longsA[i] + longsB[i]); + } + assertTrue(Arrays.equals(longsC, gLongs[6])); + + for (int i = 0; i < longsC.length; i++) { + longsC[i] = (longsA[i] + (longsB[i] >>> 137)); + longsC[i] = (longsC[i] + longsA[i] + longsB[i]); + } + assertTrue(Arrays.equals(longsC, gLongs[7])); + } + + static void test_init(int count) { + int countI = count == SMALL_LEN ? SMALL_INTS_LEN : count; + int countB = count == SMALL_LEN ? SMALL_BYTES_LEN : count; + + bytesA = new byte[countB]; + shortsA = new short[count]; + charsA = new char[count]; + intsA = new int[countI]; + longsA = new long[count]; + + bytesB = new byte[countB]; + shortsB = new short[count]; + charsB = new char[count]; + intsB = new int[countI]; + longsB = new long[count]; + + bytesC = new byte[countB]; + shortsC = new short[count]; + charsC = new char[count]; + intsC = new int[countI]; + longsC = new long[count]; + + bytesD = new byte[countB]; + shortsD = new short[count]; + + gBytes = new byte[MAX_TESTS * 2][countB]; + gShorts = new short[MAX_TESTS * 2][count]; + gChars = new char[MAX_TESTS][count]; + gInts = new int[MAX_TESTS][countI]; + gLongs = new long[MAX_TESTS][count]; + + for (int i = 0; i < countB; i++) { + bytesA[i] = (byte) r.nextInt(); + bytesB[i] = (byte) r.nextInt(); + + gBytes[0][i] = (byte) (bytesA[i] + (bytesB[i] >> 1)); + gBytes[MAX_TESTS][i] = (byte) (bytesA[i] + bytesB[i]); + gBytes[1][i] = (byte) (bytesA[i] + (bytesB[i] >> 8)); + gBytes[MAX_TESTS + 1][i] = (byte) (bytesA[i] + bytesB[i]); + gBytes[2][i] = (byte) (bytesA[i] + (bytesB[i] >> 13)); + gBytes[MAX_TESTS + 2][i] = (byte) (bytesA[i] + bytesB[i]); + gBytes[3][i] = (byte) (bytesA[i] + (bytesB[i] >> 19)); + gBytes[MAX_TESTS + 3][i] = (byte) (bytesA[i] + bytesB[i]); + gBytes[4][i] = (byte) (bytesA[i] + (bytesB[i] >>> 1)); + gBytes[MAX_TESTS + 4][i] = (byte) (bytesA[i] + bytesB[i]); + gBytes[5][i] = (byte) (bytesA[i] + (bytesB[i] >>> 8)); + gBytes[MAX_TESTS + 5][i] = (byte) (bytesA[i] + bytesB[i]); + gBytes[6][i] = (byte) (bytesA[i] + (bytesB[i] >>> 13)); + gBytes[MAX_TESTS + 6][i] = (byte) (bytesA[i] + bytesB[i]); + gBytes[7][i] = (byte) (bytesA[i] + (bytesB[i] >>> 19)); + gBytes[MAX_TESTS + 7][i] = (byte) (bytesA[i] + bytesB[i]); + } + + for (int i = 0; i < count; i++) { + shortsA[i] = (short) r.nextInt(); + charsA[i] = (char) r.nextInt(); + longsA[i] = r.nextLong(); + + shortsB[i] = (short) r.nextInt(); + charsB[i] = (char) r.nextInt(); + longsB[i] = r.nextLong(); + } + + for (int i = 0; i < count; i++) { + gShorts[0][i] = (short) (shortsA[i] + (shortsB[i] >> 5)); + gShorts[MAX_TESTS][i] = (short) (shortsA[i] + shortsB[i]); + gShorts[1][i] = (short) (shortsA[i] + (shortsB[i] >> 16)); + gShorts[MAX_TESTS + 1][i] = (short) (shortsA[i] + shortsB[i]); + gShorts[2][i] = (short) (shortsA[i] + (shortsB[i] >> 23)); + gShorts[MAX_TESTS + 2][i] = (short) (shortsA[i] + shortsB[i]); + gShorts[3][i] = (short) (shortsA[i] + (shortsB[i] >> 35)); + gShorts[MAX_TESTS + 3][i] = (short) (shortsA[i] + shortsB[i]); + gShorts[4][i] = (short) (shortsA[i] + (shortsB[i] >>> 7)); + gShorts[MAX_TESTS + 4][i] = (short) (shortsA[i] + shortsB[i]); + gShorts[5][i] = (short) (shortsA[i] + (shortsB[i] >>> 16)); + gShorts[MAX_TESTS + 5][i] = (short) (shortsA[i] + shortsB[i]); + gShorts[6][i] = (short) (shortsA[i] + (shortsB[i] >>> 23)); + gShorts[MAX_TESTS + 6][i] = (short) (shortsA[i] + shortsB[i]); + gShorts[7][i] = (short) (shortsA[i] + (shortsB[i] >>> 35)); + gShorts[MAX_TESTS + 7][i] = (short) (shortsA[i] + shortsB[i]); + + gChars[0][i] = (char) (charsA[i] + (charsB[i] >>> 4)); + gChars[0][i] = (char) (gChars[0][i] + charsA[i] + charsB[i]); + gChars[1][i] = (char) (charsA[i] + (charsB[i] >>> 16)); + gChars[1][i] = (char) (gChars[1][i] + charsA[i] + charsB[i]); + gChars[2][i] = (char) (charsA[i] + (charsB[i] >>> 19)); + gChars[2][i] = (char) (gChars[2][i] + charsA[i] + charsB[i]); + gChars[3][i] = (char) (charsA[i] + (charsB[i] >>> 35)); + gChars[3][i] = (char) (gChars[3][i] + charsA[i] + charsB[i]); + + gLongs[0][i] = longsA[i] + (longsB[i] >> 37); + gLongs[0][i] = gLongs[0][i] + longsA[i] + longsB[i]; + gLongs[1][i] = longsA[i] + (longsB[i] >> 64); + gLongs[1][i] = gLongs[1][i] + longsA[i] + longsB[i]; + gLongs[2][i] = longsA[i] + (longsB[i] >> 93); + gLongs[2][i] = gLongs[2][i] + longsA[i] + longsB[i]; + gLongs[3][i] = longsA[i] + (longsB[i] >> 137); + gLongs[3][i] = gLongs[3][i] + longsA[i] + longsB[i]; + gLongs[4][i] = longsA[i] + (longsB[i] >>> 37); + gLongs[4][i] = gLongs[4][i] + longsA[i] + longsB[i]; + gLongs[5][i] = longsA[i] + (longsB[i] >>> 64); + gLongs[5][i] = gLongs[5][i] + longsA[i] + longsB[i]; + gLongs[6][i] = longsA[i] + (longsB[i] >>> 93); + gLongs[6][i] = gLongs[6][i] + longsA[i] + longsB[i]; + gLongs[7][i] = longsA[i] + (longsB[i] >>> 137); + gLongs[7][i] = gLongs[7][i] + longsA[i] + longsB[i]; + } + + for (int i = 0; i < intsA.length; i++) { + intsA[i] = r.nextInt(); + intsB[i] = r.nextInt(); + gInts[0][i] = intsA[i] + (intsB[i] >> 19); + gInts[0][i] = gInts[0][i] + intsA[i] + intsB[i]; + gInts[1][i] = intsA[i] + (intsB[i] >> 32); + gInts[1][i] = gInts[1][i] + intsA[i] + intsB[i]; + gInts[2][i] = intsA[i] + (intsB[i] >> 49); + gInts[2][i] = gInts[2][i] + intsA[i] + intsB[i]; + gInts[3][i] = intsA[i] + (intsB[i] >> 67); + gInts[3][i] = gInts[3][i] + intsA[i] + intsB[i]; + gInts[4][i] = intsA[i] + (intsB[i] >>> 19); + gInts[4][i] = gInts[4][i] + intsA[i] + intsB[i]; + gInts[5][i] = intsA[i] + (intsB[i] >>> 32); + gInts[5][i] = gInts[5][i] + intsA[i] + intsB[i]; + gInts[6][i] = intsA[i] + (intsB[i] >>> 49); + gInts[6][i] = gInts[6][i] + intsA[i] + intsB[i]; + gInts[7][i] = intsA[i] + (intsB[i] >>> 67); + gInts[7][i] = gInts[7][i] + intsA[i] + intsB[i]; + } + } + + static void assertTrue(boolean okay) { + if (!okay) { + throw new RuntimeException("Test Failed"); + } + } +} diff --git a/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java b/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java index 7d39496831a..68313ca2cac 100644 --- a/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java +++ b/test/hotspot/jtreg/compiler/ciReplay/CiReplayBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,7 @@ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.Asserts; import jdk.test.lib.Utils; +import jdk.test.lib.util.CoreUtils; public abstract class CiReplayBase { public static final String REPLAY_FILE_NAME = "test_replay.txt"; @@ -65,17 +66,27 @@ public abstract class CiReplayBase { "-XX:MetaspaceSize=4m", "-XX:MaxMetaspaceSize=16m", "-XX:InitialCodeCacheSize=512k", "-XX:ReservedCodeCacheSize=4m", "-XX:ThreadStackSize=512", "-XX:VMThreadStackSize=512", "-XX:CompilerThreadStackSize=512", "-XX:ParallelGCThreads=1", "-XX:CICompilerCount=2", - "-Xcomp", "-XX:CICrashAt=1", "-XX:+DumpReplayDataOnError", - "-XX:+PreferInterpreterNativeStubs", "-XX:+PrintCompilation", REPLAY_FILE_OPTION}; + "-XX:-BackgroundCompilation", "-XX:CompileCommand=inline,java.io.PrintStream::*", + "-XX:+IgnoreUnrecognizedVMOptions", "-XX:TypeProfileLevel=222", // extra profile data as a stress test + "-XX:CICrashAt=1", "-XX:+DumpReplayDataOnError", + "-XX:+PreferInterpreterNativeStubs", REPLAY_FILE_OPTION}; private static final String[] REPLAY_OPTIONS = new String[]{DISABLE_COREDUMP_ON_CRASH, + "-XX:+IgnoreUnrecognizedVMOptions", "-XX:TypeProfileLevel=222", "-XX:+ReplayCompiles", REPLAY_FILE_OPTION}; protected final Optional runServer; private static int dummy; public static class TestMain { public static void main(String[] args) { - // Do something because empty methods might not be called/compiled. - dummy = 42; + for (int i = 0; i < 20_000; i++) { + test(i); + } + } + + static void test(int i) { + if ((i % 1000) == 0) { + System.out.println("Hello World!"); + } } } @@ -103,7 +114,7 @@ public CiReplayBase(String args[]) { public void runTest(boolean needCoreDump, String... args) { cleanup(); - if (generateReplay(needCoreDump)) { + if (generateReplay(needCoreDump, args)) { testAction(); cleanup(); } else { @@ -143,11 +154,16 @@ public boolean generateReplay(boolean needCoreDump, String... vmopts) { options.addAll(Arrays.asList(REPLAY_GENERATION_OPTIONS)); options.addAll(Arrays.asList(vmopts)); options.add(needCoreDump ? ENABLE_COREDUMP_ON_CRASH : DISABLE_COREDUMP_ON_CRASH); - options.add(TestMain.class.getName()); if (needCoreDump) { - crashOut = ProcessTools.executeProcess(getTestJvmCommandlineWithPrefix( - RUN_SHELL_NO_LIMIT, options.toArray(new String[0]))); + // CiReplayBase$TestMain needs to be quoted because of shell eval + options.add("-XX:CompileOnly='" + TestMain.class.getName() + "::test'"); + options.add("'" + TestMain.class.getName() + "'"); + crashOut = ProcessTools.executeProcess( + CoreUtils.addCoreUlimitCommand( + ProcessTools.createTestJvm(options.toArray(new String[0])))); } else { + options.add("-XX:CompileOnly=" + TestMain.class.getName() + "::test"); + options.add(TestMain.class.getName()); crashOut = ProcessTools.executeProcess(ProcessTools.createTestJvm(options)); } crashOutputString = crashOut.getOutput(); @@ -159,18 +175,8 @@ public boolean generateReplay(boolean needCoreDump, String... vmopts) { throw new Error("Can't create replay: " + t, t); } if (needCoreDump) { - String coreFileLocation = getCoreFileLocation(crashOutputString); - if (coreFileLocation == null) { - if (Platform.isOSX()) { - File coresDir = new File("/cores"); - if (!coresDir.isDirectory() || !coresDir.canWrite()) { - return false; - } - } - throw new Error("Couldn't find core file location in: '" + crashOutputString + "'"); - } try { - Asserts.assertGT(new File(coreFileLocation).length(), 0L, "Unexpected core size"); + String coreFileLocation = CoreUtils.getCoreFileLocation(crashOutputString, crashOut.pid()); Files.move(Paths.get(coreFileLocation), Paths.get(TEST_CORE_FILE_NAME)); } catch (IOException ioe) { throw new Error("Can't move core file: " + ioe, ioe); @@ -250,48 +256,6 @@ public void nonTieredTests(int compLevel) { } } - // lets search few possible locations using process output and return existing location - private String getCoreFileLocation(String crashOutputString) { - Asserts.assertTrue(crashOutputString.contains(LOCATIONS_STRING), - "Output doesn't contain the location of core file, see crash.out"); - String stringWithLocation = Arrays.stream(crashOutputString.split("\\r?\\n")) - .filter(str -> str.contains(LOCATIONS_STRING)) - .findFirst() - .get(); - stringWithLocation = stringWithLocation.substring(stringWithLocation - .indexOf(LOCATIONS_STRING) + LOCATIONS_STRING.length()); - String coreWithPid; - if (stringWithLocation.contains("or ") && !Platform.isWindows()) { - Matcher m = Pattern.compile("or.* ([^ ]+[^\\)])\\)?").matcher(stringWithLocation); - if (!m.find()) { - throw new Error("Couldn't find path to core inside location string"); - } - coreWithPid = m.group(1); - } else { - coreWithPid = stringWithLocation.trim(); - } - if (new File(coreWithPid).exists()) { - return coreWithPid; - } - String justCore = Paths.get("core").toString(); - if (new File(justCore).exists()) { - return justCore; - } - Path coreWithPidPath = Paths.get(coreWithPid); - String justFile = coreWithPidPath.getFileName().toString(); - if (new File(justFile).exists()) { - return justFile; - } - Path parent = coreWithPidPath.getParent(); - if (parent != null) { - String coreWithoutPid = parent.resolve("core").toString(); - if (new File(coreWithoutPid).exists()) { - return coreWithoutPid; - } - } - return null; - } - private String[] getTestJvmCommandlineWithPrefix(String prefix, String... args) { try { String cmd = ProcessTools.getCommandLine(ProcessTools.createTestJvm(args)); diff --git a/test/hotspot/jtreg/compiler/ciReplay/SABase.java b/test/hotspot/jtreg/compiler/ciReplay/SABase.java index 405b9f104d1..db576d73631 100644 --- a/test/hotspot/jtreg/compiler/ciReplay/SABase.java +++ b/test/hotspot/jtreg/compiler/ciReplay/SABase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ import java.nio.file.Files; import java.nio.file.Paths; +import java.io.BufferedReader; +import java.io.FileReader; import java.io.IOException; import java.io.File; import java.io.FileInputStream; @@ -41,7 +43,19 @@ public class SABase extends CiReplayBase { public static void main(String args[]) throws Exception { checkSetLimits(); - new SABase(args).runTest(/* needCoreDump = */ true, args); + SABase base = new SABase(args); + boolean c2 = base.runServer.orElseThrow(() -> new Error("runServer must be set")); + String[] extra = {}; + if (Platform.isTieredSupported()) { + if (c2) { + // Replay produced on first compilation. We want that + // compilation delayed so profile data is produced. + extra = new String[] {"-XX:-TieredCompilation"}; + } else { + extra = new String[] {"-XX:TieredStopAtLevel=1"}; + } + } + base.runTest(/* needCoreDump = */ true, extra); } public SABase(String[] args) { @@ -96,19 +110,42 @@ public void testAction() { File replay = new File(REPLAY_FILE_NAME); Asserts.assertTrue(replay.exists() && replay.isFile() && replay.length() > 0, "Replay data wasn't generated by SA"); + // other than comment lines, content of 2 files should be identical try { - FileInputStream rep = new FileInputStream(replay); - FileInputStream repCopy = new FileInputStream(REPLAY_FILE_COPY); - byte repBuffer[] = new byte[512]; - byte repCopyBuffer[] = new byte[512]; - boolean filesNotEqual = false; - while(rep.available() > 0 && !filesNotEqual) { - int count = rep.read(repBuffer); - int count2 = repCopy.read(repCopyBuffer); - filesNotEqual = count != count2 || Arrays.equals(repBuffer, repCopyBuffer); + BufferedReader rep = new BufferedReader(new FileReader(replay)); + BufferedReader repCopy = new BufferedReader(new FileReader(REPLAY_FILE_COPY)); + boolean failure = false; + while (true) { + String l1; + while ((l1 = rep.readLine()) != null) { + if (!l1.startsWith("#")) { + break; + } + } + String l2; + while ((l2 = repCopy.readLine()) != null) { + if (!l2.startsWith("#")) { + break; + } + } + if (l1 == null || l2 == null) { + if (l1 != null || l2 != null) { + System.out.println("Warning: replay files are not equal"); + System.out.println("1: " + l1); + System.out.println("2: " + l2); + failure = true; + } + break; + } + if (!l1.equals(l2)) { + System.out.println("Warning: replay files are not equal"); + System.out.println("1: " + l1); + System.out.println("2: " + l2); + failure = true; + } } - if (filesNotEqual) { - System.out.println("Warning: replay files are not equal"); + if (failure) { + throw new RuntimeException("Warning: replay files are not equal"); } } catch (IOException ioe) { throw new Error("Can't read replay files: " + ioe, ioe); diff --git a/test/hotspot/jtreg/compiler/ciReplay/VMBase.java b/test/hotspot/jtreg/compiler/ciReplay/VMBase.java index c8ca9d08469..a4271fada15 100644 --- a/test/hotspot/jtreg/compiler/ciReplay/VMBase.java +++ b/test/hotspot/jtreg/compiler/ciReplay/VMBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ public class VMBase extends CiReplayBase { public static void main(String args[]) { - new VMBase(args).runTest(/* needCoreDump = */ false, args); + new VMBase(args).runTest(/* needCoreDump = */ false); } public VMBase(String[] args) { diff --git a/test/hotspot/jtreg/compiler/loopopts/TestLoadPinnedAfterAllocate.java b/test/hotspot/jtreg/compiler/loopopts/TestLoadPinnedAfterAllocate.java new file mode 100644 index 00000000000..c16945060e0 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestLoadPinnedAfterAllocate.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8260709 + * @summary C2: assert(false) failed: unscheduable graph + * + * @run main/othervm -XX:-BackgroundCompilation TestLoadPinnedAfterAllocate + * + */ + +public class TestLoadPinnedAfterAllocate { + private int field; + private static volatile int barrier; + private static Object field2; + + public static void main(String[] args) { + final TestLoadPinnedAfterAllocate test = new TestLoadPinnedAfterAllocate(); + for (int i = 0; i < 20_000; i++) { + test.test(1, 10); + } + } + + private int test(int start, int stop) { + int[] array = new int[10]; + for (int j = 0; j < 10; j++) { + barrier = 1; + // early control for field load below + for (int i = 1; i < 10; i *= 2) { + field2 = array; + array = new int[10]; + // late control for field load below + } + } + int v = field; + array[0] = v; + return v+v; + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestLoopLimitNodeElimination.java b/test/hotspot/jtreg/compiler/loopopts/TestLoopLimitNodeElimination.java new file mode 100644 index 00000000000..930d38a4e19 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestLoopLimitNodeElimination.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8260370 + * @summary C2: LoopLimit node is not eliminated + * + * @run main/othervm + * -Xcomp + * -XX:CompileOnly=compiler/loopopts/TestLoopLimitNodeElimination + * compiler.loopopts.TestLoopLimitNodeElimination + */ + +package compiler.loopopts; + +// the test code is derived from a randomly generated test +public class TestLoopLimitNodeElimination { + private static class MyException extends RuntimeException { } + private static final int ITERATIONS = 100000; + private static final int SIZE = 400; + + private static int counter = 0; + + int[] array1 = new int[SIZE]; + + void test() { + int[] array2 = new int[SIZE]; + array1[2] = 0; + array1 = array1; + for (long i = 301; i > 2; i -= 2) { + int j = 1; + do { + for (int k = (int) i; k < 1; k++) { } + } while (++j < 4); + } + + counter++; + if (counter == ITERATIONS) { + throw new MyException(); + } + } + + public static void main(String[] args) { + try { + var test = new TestLoopLimitNodeElimination(); + while (true) { + test.test(); + } + } catch (MyException e) { + // expected + } + } +} + diff --git a/test/hotspot/jtreg/compiler/loopopts/TestNestedIrreducibleLoops.jasm b/test/hotspot/jtreg/compiler/loopopts/TestNestedIrreducibleLoops.jasm new file mode 100644 index 00000000000..ad79289ded4 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestNestedIrreducibleLoops.jasm @@ -0,0 +1,1939 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +super public class TestNestedIrreducibleLoops + version 45:3 +{ + Field loopCounter:I; + Field start:I; + + public Method "":"()V" + stack 1 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } + static Method addi:"(I)I" + stack 2 locals 1 + { + iload_0; + iconst_1; + iadd; + ireturn; + } + Method test:"()I" + stack 2 locals 8 + { + iconst_0; + istore_1; + iconst_0; + istore_2; + iconst_0; + istore_3; + iconst_m1; + istore 5; + iconst_2; + istore 6; + aload_0; + getfield Field start:"I"; + ifne L3135; + goto L31; + L22: iinc 2, 1; + iload_2; + iload 6; + if_icmpgt L3135; + L31: iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpeq L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmplt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iload_1; + iconst_3; + if_icmpgt L3135; + iconst_0; + istore 7; + L3084: iload 7; + iload 6; + if_icmpge L3104; + iload_1; + invokestatic Method addi:"(I)I"; + ifeq L3104; + iinc 7, 1; + goto L3084; + L3104: iload_1; + iload 6; + if_icmpge L3135; + iload_1; + invokestatic Method addi:"(I)I"; + bipush 84; + if_icmpne L3135; + iload_1; + bipush 88; + iadd; + iload 6; + if_icmpge L3135; + iconst_1; + ireturn; + L3130: iload 5; + iflt L3153; + L3135: iload_1; + invokestatic Method addi:"(I)I"; + istore_1; + iinc 3, 1; + iload_3; + aload_0; + getfield Field loopCounter:"I"; + if_icmplt L3130; + iconst_0; + ireturn; + L3153: iload 5; + iflt L22; + iconst_0; + ireturn; + } + +} // end Class TestNestedIrreducibleLoops diff --git a/test/hotspot/jtreg/compiler/loopopts/TestNestedIrreducibleLoopsMain.java b/test/hotspot/jtreg/compiler/loopopts/TestNestedIrreducibleLoopsMain.java new file mode 100644 index 00000000000..65b26bf76c1 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestNestedIrreducibleLoopsMain.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8253353 + * @summary Tests custom bytecode with deep nested irreducible loops. + * + * @compile TestNestedIrreducibleLoops.jasm + * @run main/othervm -Xbatch -XX:CompileCommand=dontinline,TestNestedIrreducibleLoops::* + * -XX:CompileCommand=exclude,TestNestedIrreducibleLoopsMain::main + * TestNestedIrreducibleLoopsMain + */ + +public class TestNestedIrreducibleLoopsMain { + public static void main(String[] args) { + TestNestedIrreducibleLoops t = new TestNestedIrreducibleLoops(); + t.loopCounter = 3; + int j; + for (int i = 0; i < 11000; i++) { + t.start = i & 0x3ff; + j = t.test(); // Produces deep nested irreducible loops + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestPickFirstMemoryState.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestPickFirstMemoryState.java new file mode 100644 index 00000000000..488e32c416a --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestPickFirstMemoryState.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/** + * @test + * @requires vm.compiler2.enabled + * @bug 8240281 + * @summary Test which needs to select the memory state of the first load in a load pack in SuperWord::co_locate_pack. + * + * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.loopopts.superword.TestPickFirstMemoryState::* + * compiler.loopopts.superword.TestPickFirstMemoryState + * @run main/othervm -XX:CompileCommand=dontinline,compiler.loopopts.superword.TestPickFirstMemoryState::* + * compiler.loopopts.superword.TestPickFirstMemoryState + */ + +package compiler.loopopts.superword; + +public class TestPickFirstMemoryState { + + static int iArrFld[] = new int[50]; + + static int test() { + int x = 2; + for (int i = 50; i > 9; i--) { + // We create an AddI pack and a LoadI pack for the following loop. The StoreI pack gets filtered. When + // finding the memory state for the load pack, we cannot pick the memory state from the last load as + // the stores (which are not vectorized) could interfere and be executed before the load pack (already + // writing 'j' to iArrFld which is afterwards loaded by the load vector operation). This leads to a + // wrong result for 'x'. We must take the memory state of the first load where we have not yet assigned + // any new values ('j') to the iArrFld array. + x = 2; + for (int j = 10; j < 50; j++) { + x += iArrFld[j]; // AddI pack + LoadI pack + iArrFld[j] = j; // StoreI pack that gets removed while filtering packs + } + reset(); + } + + return x; + } + + static int test2() { + int x = 2; + int y = 3; + for (int i = 50; i > 9; i--) { + x = 2; + for (int j = 10; j < 50; j++) { + x += iArrFld[j]; + iArrFld[j] = (y++); + } + reset(); + } + return x; + } + + static int test3() { + int x = 2; + for (int i = 50; i > 9; i--) { + x = 2; + int y = i; + for (int j = 10; j < 50; j++) { + y++; + x += iArrFld[j]; + iArrFld[j] = y; + } + reset(); + } + return x; + } + + static int test4() { + int x = 2; + long y = 3L; + for (int i = 50; i > 9; i--) { + x = 2; + for (int j = 10; j < 50; j++) { + x += iArrFld[j]; + iArrFld[j] = (int)(y++); + } + reset(); + } + return x; + } + + public static void main(String[] strArr) { + for (int i = 0; i < 5000; i++) { + reset(); + int x = test(); + if (x != 202) { + throw new RuntimeException("test() wrong result: " + x); + } + x = test2(); + if (x != 202) { + throw new RuntimeException("test2() wrong result: " + x); + } + x = test3(); + if (x != 202) { + throw new RuntimeException("test3() wrong result: " + x); + } + x = test4(); + if (x != 202) { + throw new RuntimeException("test4() wrong result: " + x); + } + } + } + + public static void reset() { + for (int i = 0; i < iArrFld.length; i++) { + iArrFld[i] = 5; + } + } +} + diff --git a/test/hotspot/jtreg/compiler/uncommontrap/UncommonTrapLeak.java b/test/hotspot/jtreg/compiler/uncommontrap/UncommonTrapLeak.java new file mode 100644 index 00000000000..5593f502614 --- /dev/null +++ b/test/hotspot/jtreg/compiler/uncommontrap/UncommonTrapLeak.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.ref.WeakReference; + +/* + * @test + * @bug 8260473 + * @summary Handle leak might cause object not collected as expected + * + * @run main/othervm -XX:-Inline -XX:-TieredCompilation -XX:CompileCommand=compileonly,UncommonTrapLeak.foo + * -XX:CompileThreshold=100 -XX:-BackgroundCompilation UncommonTrapLeak + * + * @author Hui Shi + */ +public class UncommonTrapLeak { + static WeakReference ref = null; + static int val = 0; + public static void main(String args[]) { + for (int i = 0; i < 300; i++) { + val++; + foo(i); + System.gc(); + if (ref.get() != null) { + throw new RuntimeException("Failed: referent not collected after trap " + ref.get()); + } + if (i % 100 == 0) { + System.out.println(i); + } + } + } + + static void foo(int i) { + Object o = new Object(); + ref = new WeakReference(o); + if (val == 200) { + // trigger Deoptimization::uncommon_trap + if (o instanceof UncommonTrapLeak) { + } + } + } +} + diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypeTest.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypeTest.java index bca83433aa9..56ae70b04c1 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypeTest.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypeTest.java @@ -146,9 +146,6 @@ public abstract class InlineTypeTest { private static final boolean SHUFFLE_TESTS = Boolean.parseBoolean(System.getProperty("ShuffleTests", "true")); private static final boolean PREFER_CL_FLAGS = Boolean.parseBoolean(System.getProperty("PreferCommandLineFlags", "false")); - // "jtreg -DXcomp=true" runs all the scenarios with -Xcomp. This is faster than "jtreg -javaoptions:-Xcomp". - protected static final boolean RUN_SCENARIOS_WITH_XCOMP = Boolean.parseBoolean(System.getProperty("Xcomp", "false")); - // Pre-defined settings private static final String[] defaultFlags = { "-XX:-BackgroundCompilation"}; @@ -368,9 +365,6 @@ public static void main(String[] args) throws Throwable { if (!PREFER_CL_FLAGS) { cmds = InputArguments.getVmInputArgs(); } - if (RUN_SCENARIOS_WITH_XCOMP) { - cmds = concat(cmds, "-Xcomp"); - } cmds = concat(cmds, test.getVMParameters(i)); cmds = concat(cmds, test.getExtraVMParameters(i)); if (PREFER_CL_FLAGS) { @@ -578,9 +572,7 @@ private void parseOutput(String output) throws Exception { continue; } String graph = compilations.get(testName); - if (PRINT_GRAPH) { - System.out.println("\nGraph for " + testName + "\n" + graph); - } + System.out.println("\nGraph for " + testName + "\n" + graph); // Parse graph using regular expressions to determine if it contains forbidden nodes Test[] annos = test.getAnnotationsByType(Test.class); Test anno = Arrays.stream(annos).filter(TestAnnotation::find).findFirst().orElse(null); diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue1.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue1.java index ddf448087d7..016ebf4dc41 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue1.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue1.java @@ -23,7 +23,7 @@ package compiler.valhalla.inlinetypes; -public final inline class MyValue1 extends MyAbstract { +public final primitive class MyValue1 extends MyAbstract { static int s; static final long sf = InlineTypeTest.rL; final int x; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue2.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue2.java index 476049b054f..859708d8575 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue2.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue2.java @@ -23,7 +23,7 @@ package compiler.valhalla.inlinetypes; -final inline class MyValue2Inline { +final primitive class MyValue2Inline { final double d; final long l; @@ -57,7 +57,7 @@ public static MyValue2Inline createWithFieldsInline(double d, long l) { } } -public final inline class MyValue2 extends MyAbstract { +public final primitive class MyValue2 extends MyAbstract { final int x; final byte y; final MyValue2Inline v; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue3.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue3.java index d851feb9bb8..fa3b468a790 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue3.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue3.java @@ -26,7 +26,7 @@ import jdk.test.lib.Asserts; import jdk.test.lib.Utils; -final inline class MyValue3Inline { +final primitive class MyValue3Inline { final float f7; final double f8; @@ -62,7 +62,7 @@ public static MyValue3Inline createWithFieldsInline(float f7, double f8) { // Inline type definition to stress test return of an inline type in registers // (uses all registers of calling convention on x86_64) -public final inline class MyValue3 extends MyAbstract { +public final primitive class MyValue3 extends MyAbstract { final char c; final byte bb; final short s; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue4.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue4.java index cb11e5d83e2..fcf3f38d7ea 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue4.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValue4.java @@ -24,7 +24,7 @@ package compiler.valhalla.inlinetypes; // Inline type definition with too many fields to return in registers -final inline class MyValue4 extends MyAbstract { +final primitive class MyValue4 extends MyAbstract { final MyValue3 v1; final MyValue3 v2; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValueEmpty.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValueEmpty.java index d976e14bc88..7396f0b42f8 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValueEmpty.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/MyValueEmpty.java @@ -23,7 +23,7 @@ package compiler.valhalla.inlinetypes; -public final inline class MyValueEmpty extends MyAbstract { +public final primitive class MyValueEmpty extends MyAbstract { public long hash() { return 0; } public MyValueEmpty copy(MyValueEmpty other) { return other; } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/Point.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/Point.java index 98549039bc9..0a57bc4e990 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/Point.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/Point.java @@ -23,7 +23,7 @@ package compiler.valhalla.inlinetypes; -public inline class Point { +public primitive class Point { int x = 4; int y = 7; } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/Rectangle.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/Rectangle.java index 1faddb3df70..8d2d3c9bf3e 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/Rectangle.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/Rectangle.java @@ -23,7 +23,7 @@ package compiler.valhalla.inlinetypes; -public inline class Rectangle { +public primitive class Rectangle { Point p0 = new Point(); Point p1 = new Point(); -} \ No newline at end of file +} diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/SimpleInlineType.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/SimpleInlineType.java index 080f927512b..c09cb8d599c 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/SimpleInlineType.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/SimpleInlineType.java @@ -21,7 +21,7 @@ * questions. */ -final inline class SimpleInlineType { +final primitive class SimpleInlineType { final int x; private SimpleInlineType() { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayAccessDeopt.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayAccessDeopt.java index 6dce565d8cb..936226d6358 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayAccessDeopt.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayAccessDeopt.java @@ -33,7 +33,7 @@ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; -final inline class MyValue1 { +final primitive class MyValue1 { public final int x = 0; } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayCopyWithOops.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayCopyWithOops.java index 7fb343c0ed7..58879fb897a 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayCopyWithOops.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayCopyWithOops.java @@ -49,7 +49,7 @@ static class MyObject { long val = Integer.MAX_VALUE; } - static inline class ManyOops { + static primitive class ManyOops { MyObject o1 = new MyObject(); MyObject o2 = new MyObject(); MyObject o3 = new MyObject(); diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrays.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrays.java index 09907a807e5..d81b398ef55 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrays.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrays.java @@ -1865,7 +1865,7 @@ public void test79_verifier(boolean warmup) { Asserts.assertEquals(result, i); } - inline static class NotFlattenable { + primitive static class NotFlattenable { private final Object o1 = null; private final Object o2 = null; private final Object o3 = null; @@ -2162,7 +2162,7 @@ public void test90_verifier(boolean warmup) { Asserts.assertEQ(test90(), true); } - inline static final class Test91Value { + primitive static final class Test91Value { public final int f0; public final int f1; public final int f2; @@ -3014,12 +3014,10 @@ public void test130_verifier(boolean warmup) { Asserts.assertEquals(empty, MyValueEmpty.default); } - static inline class EmptyContainer { + static primitive class EmptyContainer { MyValueEmpty empty = MyValueEmpty.default; } - // TODO disabled until JDK-8253893 is fixed -/* // Empty inline type container array access @Test(failOn = ALLOC + ALLOCA + LOAD + STORE) public MyValueEmpty test131(EmptyContainer[] array) { @@ -3034,7 +3032,6 @@ public void test131_verifier(boolean warmup) { Asserts.assertEquals(array[0], EmptyContainer.default); Asserts.assertEquals(empty, MyValueEmpty.default); } -*/ // Empty inline type array access with unknown array type @Test() @@ -3055,8 +3052,6 @@ public void test132_verifier(boolean warmup) { Asserts.assertEquals(empty, null); } - // TODO disabled until JDK-8253893 is fixed -/* // Empty inline type container array access with unknown array type @Test() public Object test133(Object[] array) { @@ -3075,7 +3070,6 @@ public void test133_verifier(boolean warmup) { Asserts.assertEquals(array[0], EmptyContainer.default); Asserts.assertEquals(empty, null); } -*/ // Non-escaping empty inline type array access @Test(failOn = ALLOC + ALLOCA + LOAD + STORE) @@ -3358,4 +3352,17 @@ public void test144() { public void test144_verifier(boolean warmup) { test144(); } + + // Test that array load slow path correctly initializes non-flattened field of empty inline type + @Test() + public Object test145(Object[] array) { + return array[0]; + } + + @DontCompile + public void test145_verifier(boolean warmup) { + Object[] array = new EmptyContainer[1]; + EmptyContainer empty = (EmptyContainer)test145(array); + Asserts.assertEquals(empty, EmptyContainer.default); + } } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java index 4b549af2a49..da6ec98bdfd 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java @@ -786,12 +786,12 @@ public void test36_verifier(boolean warmup) { } // Test correct loading of flattened fields - inline class Test37Value2 { + primitive class Test37Value2 { final int x = 0; final int y = 0; } - inline class Test37Value1 { + primitive class Test37Value1 { final double d = 0; final float f = 0; final Test37Value2 v = new Test37Value2(); @@ -809,7 +809,7 @@ public void test37_verifier(boolean warmup) { } // Test elimination of inline type allocations without a unique CheckCastPP - inline class Test38Value { + primitive class Test38Value { public int i; public Test38Value(int i) { this.i = i; } } @@ -836,7 +836,7 @@ public void test38_verifier(boolean warmup) { } // Tests split if with inline type Phi users - static inline class Test39Value { + static primitive class Test39Value { public int iFld1; public int iFld2; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBimorphicInlining.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBimorphicInlining.java index a6820154e53..a03765a40cf 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBimorphicInlining.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBimorphicInlining.java @@ -47,7 +47,7 @@ interface MyInterface { public MyInterface hash(MyInterface arg); } -inline final class TestValue1 implements MyInterface { +primitive final class TestValue1 implements MyInterface { final int x; public TestValue1(int x) { @@ -59,7 +59,7 @@ public TestValue1 hash(MyInterface arg) { } } -inline final class TestValue2 implements MyInterface { +primitive final class TestValue2 implements MyInterface { final int x; public TestValue2(int x) { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferTearing.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferTearing.java index 03f1779c8e8..17500842a54 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferTearing.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBufferTearing.java @@ -54,7 +54,7 @@ * compiler.valhalla.inlinetypes.TestBufferTearing */ -inline class MyValue { +primitive class MyValue { int x; int y; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java index f468e7fa23e..7b15092d82b 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java @@ -106,7 +106,7 @@ public void test1_verifier(boolean warmup) { Asserts.assertEQ(r2, 0x1234567812345678L); } - static inline class SimpleValue2 { + static primitive class SimpleValue2 { final int value; SimpleValue2(int value) { this.value = value; @@ -207,7 +207,7 @@ public void test6_verifier(boolean warmup) { } // Test 1st level sub-element access to non-flattened field - static inline class Big { + static primitive class Big { long l0,l1,l2,l3,l4,l5,l6,l7,l8,l9,l10,l11,l12,l13,l14,l15,l16,l17,l18,l19 ; Big(long n) { @@ -240,7 +240,7 @@ void check(long n, int i) { } } - static inline class TestValue { + static primitive class TestValue { int i; Big big; @@ -288,7 +288,7 @@ public void test8_verifier(boolean warmup) { // (read/write are not performed, pre-allocated instance is used for reads) // Most tests check that error conditions are still correctly handled // (OOB, null pointer) - static inline class EmptyType {} + static primitive class EmptyType {} @Test(compLevel=C1) public EmptyType test9() { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java index 426b52a5e12..4c634014266 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java @@ -66,7 +66,7 @@ public class TestC2CCalls { public static final int COMP_LEVEL_FULL_OPTIMIZATION = 4; // C2 or JVMCI public static final int rI = Utils.getRandomInstance().nextInt() % 1000; - static inline class OtherVal { + static primitive class OtherVal { public final int x; private OtherVal(int x) { @@ -89,7 +89,7 @@ static interface MyInterface1 { public int getValue(); } - static inline class MyValue1 implements MyInterface1 { + static primitive class MyValue1 implements MyInterface1 { public final int x; private MyValue1(int x) { @@ -155,7 +155,7 @@ public MyValue1 test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, i } } - static inline class MyValue2 implements MyInterface1 { + static primitive class MyValue2 implements MyInterface1 { public final int x; private MyValue2(int x) { @@ -221,7 +221,7 @@ public MyValue2 test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, i } } - static inline class MyValue3 implements MyInterface1 { + static primitive class MyValue3 implements MyInterface1 { public final double d1; public final double d2; public final double d3; @@ -271,7 +271,7 @@ public MyValue3 test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, i } } - static inline class MyValue4 implements MyInterface1 { + static primitive class MyValue4 implements MyInterface1 { public final int x1; public final int x2; public final int x3; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConvention.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConvention.java index 89ef18e5d5a..6b8d8088a69 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConvention.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConvention.java @@ -456,7 +456,7 @@ public void test22_verifier(boolean warmup) { } // Test calling a method that has circular register/stack dependencies when unpacking inline type arguments - inline class TestValue23 { + primitive class TestValue23 { final double f1; TestValue23(double val) { f1 = val; @@ -528,7 +528,7 @@ public void test26_verifier(boolean warmup) { } // Test calling convention with deep hierarchy of flattened fields - final inline class Test27Value1 { + final primitive class Test27Value1 { final Test27Value2 valueField; private Test27Value1(Test27Value2 val2) { @@ -541,7 +541,7 @@ public int test(Test27Value1 val1) { } } - final inline class Test27Value2 { + final primitive class Test27Value2 { final Test27Value3 valueField; private Test27Value2(Test27Value3 val3) { @@ -554,7 +554,7 @@ public int test(Test27Value2 val2) { } } - final inline class Test27Value3 { + final primitive class Test27Value3 { final int x; private Test27Value3(int x) { @@ -767,7 +767,7 @@ public void test36_verifier(boolean warmup) throws Exception { // Test method resolution with scalarized inline type receiver at invokespecial static final MethodHandle test37_mh; - inline class Test37Value { + primitive class Test37Value { int x = rI; @DontInline @@ -802,7 +802,7 @@ public void test38_verifier(boolean warmup) { Asserts.assertEQ(res, vt); } - static inline class LargeValueWithOops { + static primitive class LargeValueWithOops { // Use all 6 int registers + 50/2 on stack = 29 Object o1 = null; Object o2 = null; @@ -835,7 +835,7 @@ static inline class LargeValueWithOops { Object o29 = null; } - static inline class LargeValueWithoutOops { + static primitive class LargeValueWithoutOops { // Use all 6 int registers + 50/2 on stack = 29 int i1 = 0; int i2 = 0; @@ -918,7 +918,7 @@ public void test41_verifier(boolean warmup) { // More empty inline type tests with containers - static inline class EmptyContainer { + static primitive class EmptyContainer { private MyValueEmpty empty; EmptyContainer(MyValueEmpty empty) { @@ -932,7 +932,7 @@ static inline class EmptyContainer { MyValueEmpty getNoInline() { return empty; } } - static inline class MixedContainer { + static primitive class MixedContainer { public int val; private EmptyContainer empty; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java index 4d312f9d593..a7358a54851 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java @@ -111,7 +111,7 @@ public static void main(String[] args) throws Throwable { RefPoint_Access_Impl2.class); } - static inline class Point { + static primitive class Point { final int x; final int y; public Point(int x, int y) { @@ -228,7 +228,7 @@ static class MyImplPojo3 implements Intf { public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 1; } } - static inline class MyImplVal1 implements Intf { + static primitive class MyImplVal1 implements Intf { final int field; MyImplVal1() { field = 11000; @@ -241,7 +241,7 @@ static inline class MyImplVal1 implements Intf { public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 300; } } - static inline class MyImplVal2 implements Intf { + static primitive class MyImplVal2 implements Intf { final int field; MyImplVal2() { field = 12000; @@ -254,7 +254,7 @@ static inline class MyImplVal2 implements Intf { public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 300; } } - static inline class MyImplVal1X implements Intf { + static primitive class MyImplVal1X implements Intf { final int field; MyImplVal1X() { field = 11000; @@ -267,7 +267,7 @@ static inline class MyImplVal1X implements Intf { public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 300; } } - static inline class MyImplVal2X implements Intf { + static primitive class MyImplVal2X implements Intf { final int field; MyImplVal2X() { field = 12000; @@ -292,7 +292,7 @@ static Intf getIntf(int i) { return intfs[n]; } - static inline class FixedPoints { + static primitive class FixedPoints { final boolean Z0 = false; final boolean Z1 = true; final byte B = (byte)2; @@ -303,7 +303,7 @@ static inline class FixedPoints { } static FixedPoints fixedPointsField = new FixedPoints(); - static inline class FloatPoint { + static primitive class FloatPoint { final float x; final float y; public FloatPoint(float x, float y) { @@ -311,7 +311,7 @@ public FloatPoint(float x, float y) { this.y = y; } } - static inline class DoublePoint { + static primitive class DoublePoint { final double x; final double y; public DoublePoint(double x, double y) { @@ -322,7 +322,7 @@ public DoublePoint(double x, double y) { static FloatPoint floatPointField = new FloatPoint(123.456f, 789.012f); static DoublePoint doublePointField = new DoublePoint(123.456, 789.012); - static inline class EightFloats { + static primitive class EightFloats { float f1, f2, f3, f4, f5, f6, f7, f8; public EightFloats() { f1 = 1.1f; @@ -352,7 +352,7 @@ static interface RefPoint_Access { public int func2(RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2); } - static inline class RefPoint implements RefPoint_Access { + static primitive class RefPoint implements RefPoint_Access { final Number x; final Number y; public RefPoint(int x, int y) { @@ -441,7 +441,7 @@ static RefPoint_Access get_RefPoint_Access() { // This inline class has too many fields to fit in registers on x64 for // InlineTypeReturnedAsFields. - static inline class TooBigToReturnAsFields { + static primitive class TooBigToReturnAsFields { int a0 = 0; int a1 = 1; int a2 = 2; @@ -2170,7 +2170,7 @@ public void test103() { test103_v = new Test103Value(); // invokestatic "Test103Value.()QTest103Value;" } - static inline class Test103Value { + static primitive class Test103Value { int x = rI; } @@ -2195,7 +2195,7 @@ public void test104() { test104_v = new Test104Value(); // invokestatic "Test104Value.()QTest104Value;" } - static inline class Test104Value { + static primitive class Test104Value { long x0 = rL; long x1 = rL; long x2 = rL; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeadAllocationRemoval.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeadAllocationRemoval.java index 9044bea6def..ed7171d1662 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeadAllocationRemoval.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeadAllocationRemoval.java @@ -38,7 +38,7 @@ public static void main(String[] args) { } } -inline class MyValue { +primitive class MyValue { public static long instanceCount = 0; public float fFld = 0; public boolean bFld = true; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeoptimizationWhenBuffering.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeoptimizationWhenBuffering.java index 238626ce311..07ad4836af3 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeoptimizationWhenBuffering.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeoptimizationWhenBuffering.java @@ -74,7 +74,7 @@ * compiler.valhalla.inlinetypes.TestDeoptimizationWhenBuffering */ -final inline class MyValue1 { +final primitive class MyValue1 { static int cnt = 0; final int x; final MyValue2 vtField1; @@ -95,7 +95,7 @@ public MyValue1 testWithField(int x) { } } -final inline class MyValue2 { +final primitive class MyValue2 { static int cnt = 0; final int x; public MyValue2() { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayAliasesCardMark.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayAliasesCardMark.java index eeae355ba17..0fd6890a447 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayAliasesCardMark.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayAliasesCardMark.java @@ -31,7 +31,7 @@ */ -inline class Test0 { +primitive class Test0 { int x = 42; short[] array = new short[7]; } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java index e94d1fad784..0491078f5b0 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java @@ -32,7 +32,7 @@ import jdk.test.lib.Asserts; -final inline class MyValue1 { +final primitive class MyValue1 { final Object o1; final Object o2; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGenerated.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGenerated.java index 47469c73bb5..f442b150974 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGenerated.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGenerated.java @@ -30,16 +30,16 @@ package compiler.valhalla.inlinetypes; -inline class EmptyValue { +primitive class EmptyValue { } -inline class MyValue1 { +primitive class MyValue1 { int x = 42; int[] array = new int[1]; } -inline class MyValue2 { +primitive class MyValue2 { int[] a = new int[1]; int[] b = new int[6]; int[] c = new int[5]; @@ -118,6 +118,10 @@ void test7(boolean b) { } } + boolean test8(MyValue1[] array) { + return array[0].array == array[0].array; + } + public static void main(String[] args) { TestGenerated t = new TestGenerated(); EmptyValue[] array1 = { new EmptyValue() }; @@ -132,6 +136,7 @@ public static void main(String[] args) { t.test5(array3); t.test6(); t.test7(false); + t.test8(array3); } } } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java index dcfe99bc45c..bb984e3d5ae 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java @@ -181,12 +181,12 @@ public void test5_verifier(boolean warmup) { Asserts.assertEQ(nsfe.getMessage(), "x"); } - static inline class EmptyType { } - static inline class EmptyContainer { + static primitive class EmptyType { } + static primitive class EmptyContainer { int i = 0; EmptyType et = new EmptyType(); } - static inline class Container { + static primitive class Container { EmptyContainer container0 = new EmptyContainer(); EmptyContainer container1 = new EmptyContainer(); } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIntrinsics.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIntrinsics.java index 1e70812f056..823a0156d31 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIntrinsics.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIntrinsics.java @@ -430,7 +430,7 @@ public void test24_verifier(boolean warmup) { } // Test copyOf intrinsic with allocated inline type in it's debug information - final inline class Test25Value { + final primitive class Test25Value { final int x; public Test25Value() { this.x = 42; @@ -1075,4 +1075,59 @@ public void test57() { public void test57_verifier(boolean warmup) { test57(); } + + // Test unsafe allocation + @Test() + public boolean test58(Class c1, Class c2) throws Exception { + Object obj1 = U.allocateInstance(c1); + Object obj2 = U.allocateInstance(c2); + return obj1 == obj2; + } + + @DontCompile + public void test58_verifier(boolean warmup) throws Exception { + boolean res = test58(MyValue1.class, MyValue1.class); + Asserts.assertTrue(res); + res = test58(Object.class, MyValue1.class); + Asserts.assertFalse(res); + res = test58(MyValue1.class, Object.class); + Asserts.assertFalse(res); + } + + // Test synchronization on unsafe inline type allocation + @Test() + public void test59(Class c) throws Exception { + Object obj = U.allocateInstance(c); + synchronized (obj) { + + } + } + + @DontCompile + public void test59_verifier(boolean warmup) throws Exception { + test59(Integer.class); + try { + test59(MyValue1.class); + throw new RuntimeException("test59 failed: synchronization on inline type should not succeed"); + } catch (IllegalMonitorStateException e) { + + } + } + + // Test mark word load optimization on unsafe inline type allocation + @Test() + public boolean test60(Class c1, Class c2, boolean b1, boolean b2) throws Exception { + Object obj1 = b1 ? new Object() : U.allocateInstance(c1); + Object obj2 = b2 ? new Object() : U.allocateInstance(c2); + return obj1 == obj2; + } + + @DontCompile + public void test60_verifier(boolean warmup) throws Exception { + Asserts.assertTrue(test60(MyValue1.class, MyValue1.class, false, false)); + Asserts.assertFalse(test60(MyValue1.class, MyValue2.class, false, false)); + Asserts.assertFalse(test60(MyValue1.class, MyValue1.class, false, true)); + Asserts.assertFalse(test60(MyValue1.class, MyValue1.class, true, false)); + Asserts.assertFalse(test60(MyValue1.class, MyValue1.class, true, true)); + } } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIsSubstitutableReresolution.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIsSubstitutableReresolution.java index 947beb4a932..99bf9413fb6 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIsSubstitutableReresolution.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestIsSubstitutableReresolution.java @@ -32,7 +32,7 @@ * @run main/othervm -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestIsSubstitutableReresolution::test * compiler.valhalla.inlinetypes.TestIsSubstitutableReresolution */ -final inline class MyValue { +final primitive class MyValue { final int x; public MyValue(int x) { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestJNICalls.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestJNICalls.java index 514e21f8d98..f7f65558eec 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestJNICalls.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestJNICalls.java @@ -93,7 +93,7 @@ public void test2_verifier(boolean warmup) { Asserts.assertEQ(result, vt.hash()); } - static inline class MyValueWithNative { + static primitive class MyValueWithNative { public final int x; private MyValueWithNative(int x) { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java index 25fb8b8b889..a3bac3d813a 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java @@ -328,6 +328,7 @@ public void test9_verifier(boolean warmup) { } // merge of inline types in an object local + @ForceInline public Object test10_helper() { return valueField1; } @@ -1488,7 +1489,7 @@ public void test50_verifier(boolean warmup) { } // Inline type with some non-flattened fields - final inline class Test51Value { + final primitive class Test51Value { final Object objectField1; final Object objectField2; final Object objectField3; @@ -1974,7 +1975,7 @@ public void test71_verifier(boolean warmup) { } // Test calling a method on an uninitialized inline type - final inline class Test72Value { + final primitive class Test72Value { final int x = 42; public int get() { return x; @@ -2130,7 +2131,7 @@ public void test79_verifier(boolean warmup) throws Throwable { } // Test flattened field with non-flattenend (but flattenable) inline type field - static inline class Small { + static primitive class Small { final int i; final Big big; // Too big to be flattened @@ -2140,7 +2141,7 @@ private Small() { } } - static inline class Big { + static primitive class Big { long l0,l1,l2,l3,l4,l5,l6,l7,l8,l9; long l10,l11,l12,l13,l14,l15,l16,l17,l18,l19; long l20,l21,l22,l23,l24,l25,l26,l27,l28,l29; @@ -2394,7 +2395,7 @@ public void test91_verifier(boolean warmup) { Asserts.assertFalse(test91(new Object())); } - static inline class Test92Value { + static primitive class Test92Value { final int field; public Test92Value() { field = 0x42; @@ -2912,7 +2913,7 @@ static WrapperInterface wrap(long val) { } } - static inline class LongWrapper implements WrapperInterface { + static primitive class LongWrapper implements WrapperInterface { final static LongWrapper ZERO = new LongWrapper(0); private long val; @@ -3167,7 +3168,7 @@ public static WrapperInterface2 wrap_default(long val) { } } - static inline class LongWrapper2 implements WrapperInterface2 { + static primitive class LongWrapper2 implements WrapperInterface2 { private long val; public LongWrapper2(long val) { @@ -3179,7 +3180,7 @@ public long value() { } } - static inline class InlineWrapper { + static primitive class InlineWrapper { WrapperInterface2 content; public InlineWrapper(long val) { @@ -3287,11 +3288,11 @@ public void test118_verifier(boolean warmup) { Asserts.assertTrue(res); } - static inline class EmptyContainer { + static primitive class EmptyContainer { private MyValueEmpty empty = MyValueEmpty.default; } - static inline class MixedContainer { + static primitive class MixedContainer { public int val = rI; private EmptyContainer empty = EmptyContainer.default; } @@ -3300,17 +3301,15 @@ static inline class MixedContainer { @Test public void test119(boolean deopt) { MyValueEmpty[] array1 = new MyValueEmpty[]{MyValueEmpty.default}; -// TODO disabled until JDK-8253893 is fixed -// EmptyContainer[] array2 = new EmptyContainer[]{EmptyContainer.default}; -// MixedContainer[] array3 = new MixedContainer[]{MixedContainer.default}; + EmptyContainer[] array2 = new EmptyContainer[]{EmptyContainer.default}; + MixedContainer[] array3 = new MixedContainer[]{MixedContainer.default}; if (deopt) { // uncommon trap WHITE_BOX.deoptimizeMethod(tests.get(getClass().getSimpleName() + "::test119")); } Asserts.assertEquals(array1[0], MyValueEmpty.default); -// TODO disabled until JDK-8253893 is fixed -// Asserts.assertEquals(array2[0], EmptyContainer.default); -// Asserts.assertEquals(array3[0], MixedContainer.default); + Asserts.assertEquals(array2[0], EmptyContainer.default); + Asserts.assertEquals(array3[0], MixedContainer.default); } @DontCompile @@ -3624,4 +3623,26 @@ public void test133_verifier(boolean warmup) { // Expected } } + + // Variant with non-scalarized inline type + @Test() + public static void test134(boolean b) { + Object obj = null; + if (b) { + obj = MyValue2.createWithFieldsInline(rI, rD); + } + synchronized (obj) { + + } + } + + @DontCompile + public void test134_verifier(boolean warmup) { + try { + test134(true); + throw new RuntimeException("test134 failed: no exception thrown"); + } catch (IllegalMonitorStateException ex) { + // Expected + } + } } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorldProfiling.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorldProfiling.java index 220005ea7af..813049b4dbc 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorldProfiling.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorldProfiling.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * 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,15 +57,18 @@ public class TestLWorldProfiling extends InlineTypeTest { "-XX:-UseACmpProfile", "-XX:TypeProfileLevel=0", "-XX:-MonomorphicArrayCheck", + "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation" }, { "-XX:+UseArrayLoadStoreProfile", "-XX:+UseACmpProfile", "-XX:TypeProfileLevel=0", + "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation" }, { "-XX:-UseArrayLoadStoreProfile", "-XX:-UseACmpProfile", "-XX:TypeProfileLevel=222", "-XX:-MonomorphicArrayCheck", + "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation" } }; @@ -369,7 +372,7 @@ public void test14_verifier(boolean warmup) { // null free array profiling - inline static class NotFlattenable { + primitive static class NotFlattenable { private final Object o1 = null; private final Object o2 = null; private final Object o3 = null; @@ -916,7 +919,7 @@ public void test39_verifier(boolean warmup) { // Test array access with polluted array type profile static abstract class Test40Abstract { } static class Test40Class extends Test40Abstract { } - static inline class Test40Inline extends Test40Abstract { } + static primitive class Test40Inline extends Test40Abstract { } @ForceInline public Object test40_access(Object[] array) { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNativeClone.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNativeClone.java index 914e76e229c..a2f63a64917 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNativeClone.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNativeClone.java @@ -42,7 +42,7 @@ import java.lang.reflect.Method; import jdk.test.lib.Asserts; -inline class MyValue { +primitive class MyValue { public final int x; public MyValue(int x) { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNestmateAccess.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNestmateAccess.java index fe5701d9a15..f9f3434dc51 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNestmateAccess.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNestmateAccess.java @@ -41,7 +41,7 @@ interface MyInterface { int hash(); } -inline class MyValue implements MyInterface { +primitive class MyValue implements MyInterface { int x = 42; int y = 43; @@ -69,7 +69,7 @@ public MyInterface test() { } // Same as Test1 but outer class is an inline type -inline class Test2 { +primitive class Test2 { private MyValue vt; public Test2(final MyValue vt) { @@ -123,7 +123,7 @@ public MyInterface test() { } // Same as Test2 but with static field -inline class Test5 { +primitive class Test5 { private static MyValue vt; public Test5(final MyValue vt) { @@ -158,7 +158,7 @@ public MyInterface test(MyValue init) { } // Same as Test6 but outer class is an inline type -inline class Test7 { +primitive class Test7 { private static MyValue vt; public MyInterface test(MyValue init) { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNewAcmp.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNewAcmp.java index d893a2db498..773ab0e40a8 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNewAcmp.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNewAcmp.java @@ -57,7 +57,7 @@ abstract class MyAbstract implements MyInterface { } -inline class MyValue1 extends MyAbstract { +primitive class MyValue1 extends MyAbstract { final int x; MyValue1(int x) { @@ -73,7 +73,7 @@ static MyValue1 setX(MyValue1 v, int x) { } } -inline class MyValue2 extends MyAbstract { +primitive class MyValue2 extends MyAbstract { final int x; MyValue2(int x) { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableArrays.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableArrays.java index afa360deeaf..dcfdb641795 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableArrays.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableArrays.java @@ -2495,7 +2495,7 @@ public void test95_verifier(boolean warmup) { } // Matrix multiplication test to exercise type flow analysis with nullable inline type arrays - inline static class Complex { + primitive static class Complex { private final double re; private final double im; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java index 018e2b49b27..98ab9441294 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java @@ -477,7 +477,7 @@ public void test16_verifier(boolean warmup) throws Exception { } // Test scalarization of default inline type with non-flattenable field - final inline class Test17Value { + final primitive class Test17Value { public final MyValue1.ref valueField; @ForceInline @@ -584,7 +584,7 @@ public void test20_verifier(boolean warmup) { } // Test writing null to a flattenable/non-flattenable inline type field in an inline type - final inline class Test21Value { + final primitive class Test21Value { final MyValue1.ref valueField1; final MyValue1 valueField2; final MyValue1.ref alwaysNull = null; @@ -802,7 +802,7 @@ public void test30_verifier(boolean warmup) { } // Test casting null to unloaded inline type - final inline class Test31Value { + final primitive class Test31Value { private final int i = 0; } @@ -834,11 +834,11 @@ public void test32_verifier(boolean warmup) { Asserts.assertEquals(result, null); } - static inline class Test33Value1 { + static primitive class Test33Value1 { int x = 0; } - static inline class Test33Value2 { + static primitive class Test33Value2 { Test33Value1.ref vt; public Test33Value2() { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOnStackReplacement.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOnStackReplacement.java index 8fc2399ca71..10cf2d53abc 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOnStackReplacement.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOnStackReplacement.java @@ -177,7 +177,7 @@ public void test5_verifier(boolean warmup) { } // Test OSR in method with inline type receiver - inline class Test6Value { + primitive class Test6Value { public int f = 0; public int test() { @@ -203,7 +203,7 @@ public void test6_verifier(boolean warmup) { } // Similar to test6 but with more fields and reserved stack entry - static inline class Test7Value1 { + static primitive class Test7Value1 { public int i1 = rI; public int i2 = rI; public int i3 = rI; @@ -212,7 +212,7 @@ static inline class Test7Value1 { public int i6 = rI; } - static inline class Test7Value2 { + static primitive class Test7Value2 { public int i1 = rI; public int i2 = rI; public int i3 = rI; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOptimizeKlassCmp.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOptimizeKlassCmp.java index f322ecb27b4..2a845ec3ab7 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOptimizeKlassCmp.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOptimizeKlassCmp.java @@ -34,7 +34,7 @@ import jdk.test.lib.Asserts; -inline class MyValue { +primitive class MyValue { public final int x; public MyValue(int x) { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestStressReturnBuffering.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestStressReturnBuffering.java index ad0426b4682..67f38cbe762 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestStressReturnBuffering.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestStressReturnBuffering.java @@ -35,7 +35,7 @@ import jdk.test.lib.Asserts; -inline class MyValue { +primitive class MyValue { public Integer o1; public Integer o2; public Integer o3; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeArray.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeArray.java index c43fef4b1c3..0de09f53111 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeArray.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeArray.java @@ -50,7 +50,7 @@ import jdk.test.lib.Asserts; -final inline class MyValue1 { +final primitive class MyValue1 { final int foo; private MyValue1() { @@ -58,7 +58,7 @@ private MyValue1() { } } -final inline class MyValue1Box { +final primitive class MyValue1Box { final int foo; private MyValue1Box() { @@ -66,7 +66,7 @@ private MyValue1Box() { } } -final inline class MyValue2 { +final primitive class MyValue2 { final int foo; public MyValue2(int n) { @@ -74,7 +74,7 @@ public MyValue2(int n) { } } -final inline class MyValue2Box { +final primitive class MyValue2Box { final int foo; public MyValue2Box(int n) { @@ -82,7 +82,7 @@ public MyValue2Box(int n) { } } -final inline class MyValue3 { +final primitive class MyValue3 { final int foo; public MyValue3(int n) { @@ -90,7 +90,7 @@ public MyValue3(int n) { } } -final inline class MyValue3Box { +final primitive class MyValue3Box { final int foo; public MyValue3Box(int n) { @@ -98,7 +98,7 @@ public MyValue3Box(int n) { } } -final inline class MyValue4 { +final primitive class MyValue4 { final int foo; public MyValue4(int n) { @@ -106,7 +106,7 @@ public MyValue4(int n) { } } -final inline class MyValue4Box { +final primitive class MyValue4Box { final int foo; public MyValue4Box(int n) { @@ -114,7 +114,7 @@ public MyValue4Box(int n) { } } -final inline class MyValue5 { +final primitive class MyValue5 { final int foo; public MyValue5(int n) { @@ -122,7 +122,7 @@ public MyValue5(int n) { } } -final inline class MyValue6 { +final primitive class MyValue6 { final int foo; public MyValue6(int n) { @@ -134,7 +134,7 @@ public MyValue6(MyValue6 v, MyValue6[] dummy) { } } -final inline class MyValue6Box { +final primitive class MyValue6Box { final int foo; public MyValue6Box(int n) { @@ -146,7 +146,7 @@ public MyValue6Box(MyValue6Box v, MyValue6Box.ref[] dummy) { } } -final inline class MyValue7 { +final primitive class MyValue7 { final int foo; public MyValue7(int n) { @@ -154,7 +154,7 @@ public MyValue7(int n) { } } -final inline class MyValue7Box { +final primitive class MyValue7Box { final int foo; public MyValue7Box(int n) { @@ -162,25 +162,25 @@ public MyValue7Box(int n) { } } -final inline class MyValue8 { +final primitive class MyValue8 { final int foo = 123; static { TestUnloadedInlineTypeArray.MyValue8_inited = true; } } -final inline class MyValue9 { +final primitive class MyValue9 { final int foo = 123; static { TestUnloadedInlineTypeArray.MyValue9_inited = true; } } -final inline class MyValue10 { +final primitive class MyValue10 { final int foo = 42; } -final inline class MyValue11 { +final primitive class MyValue11 { final int foo = 42; } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeField.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeField.java index 24ff0ea3329..d5f7e803ae5 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeField.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeField.java @@ -76,7 +76,7 @@ public String[] getVMParameters(int scenario) { // // MyValue1 has already been loaded, because it's in the InlineType attribute of // TestUnloadedInlineTypeField, due to TestUnloadedInlineTypeField.test1_precondition(). - static final inline class MyValue1 { + static final primitive class MyValue1 { final int foo; MyValue1() { @@ -125,7 +125,7 @@ public void test1_verifier(boolean warmup) { // // MyValue2 has not been loaded, because it is not explicitly referenced by // TestUnloadedInlineTypeField. - static final inline class MyValue2 { + static final primitive class MyValue2 { final int foo; public MyValue2(int n) { @@ -174,7 +174,7 @@ public void test2_verifier(boolean warmup) { // // MyValue3 has already been loaded, because it's in the InlineType attribute of // TestUnloadedInlineTypeField, due to TestUnloadedInlineTypeField.test3_precondition(). - static final inline class MyValue3 { + static final primitive class MyValue3 { final int foo; public MyValue3() { @@ -220,7 +220,7 @@ public void test3_verifier(boolean warmup) { // Test case 4: // Same as case 1, except we use putfield instead of getfield. - static final inline class MyValue4 { + static final primitive class MyValue4 { final int foo; MyValue4(int n) { @@ -258,7 +258,7 @@ public void test4_verifier(boolean warmup) { // Test case 5: // Same as case 2, except we use putfield instead of getfield. - static final inline class MyValue5 { + static final primitive class MyValue5 { final int foo; MyValue5(int n) { @@ -308,7 +308,7 @@ public void test5_verifier(boolean warmup) { // // MyValue6 has already been loaded, because it's in the InlineType attribute of // TestUnloadedInlineTypeField, due to TestUnloadedInlineTypeField.test1_precondition(). - static final inline class MyValue6 { + static final primitive class MyValue6 { final int foo; MyValue6() { @@ -351,7 +351,7 @@ public void test6_verifier(boolean warmup) { // // MyValue7 has not been loaded, because it is not explicitly referenced by // TestUnloadedInlineTypeField. - static final inline class MyValue7 { + static final primitive class MyValue7 { final int foo; MyValue7(int n) { @@ -383,7 +383,7 @@ public void test7_verifier(boolean warmup) { // Test case 8: // Same as case 1, except holder is allocated in test method (-> no holder null check required) - static final inline class MyValue8 { + static final primitive class MyValue8 { final int foo; MyValue8() { @@ -424,7 +424,7 @@ public void test8_verifier(boolean warmup) { // Test case 9: // Same as case 2, except holder is allocated in test method (-> no holder null check required) - static final inline class MyValue9 { + static final primitive class MyValue9 { final int foo; public MyValue9(int n) { @@ -461,7 +461,7 @@ public void test9_verifier(boolean warmup) { // Test case 10: // Same as case 4, but with putfield - static final inline class MyValue10 { + static final primitive class MyValue10 { final int foo; public MyValue10() { @@ -509,7 +509,7 @@ public void test10_verifier(boolean warmup) { // Test case 11: // Same as case 4, except holder is allocated in test method (-> no holder null check required) - static final inline class MyValue11 { + static final primitive class MyValue11 { final int foo; MyValue11(int n) { @@ -549,7 +549,7 @@ public void test11_verifier(boolean warmup) { // Test case 12: // Same as case 5, except holder is allocated in test method (-> no holder null check required) - static final inline class MyValue12 { + static final primitive class MyValue12 { final int foo; MyValue12(int n) { @@ -590,7 +590,7 @@ public void test12_verifier(boolean warmup) { // Test case 13: // Same as case 10, except MyValue13 is allocated in test method - static final inline class MyValue13 { + static final primitive class MyValue13 { final int foo; public MyValue13() { @@ -636,7 +636,7 @@ public void test13_verifier(boolean warmup) { // Test case 14: // Same as case 10, except storing null - static final inline class MyValue14 { + static final primitive class MyValue14 { final int foo; public MyValue14() { @@ -682,7 +682,7 @@ public void test14_verifier(boolean warmup) { // Test case 15: // Same as case 13, except MyValue15 is unloaded - static final inline class MyValue15 { + static final primitive class MyValue15 { final int foo; public MyValue15() { @@ -792,7 +792,7 @@ public void test17_verifier(boolean warmup) { // Test case 18: // Same as test7 but with the holder being loaded - static final inline class MyValue18 { + static final primitive class MyValue18 { final int foo; MyValue18(int n) { @@ -826,7 +826,7 @@ public void test18_verifier(boolean warmup) { // Test case 19: // Same as test18 but uninitialized (null) static inline type field - static final inline class MyValue19 { + static final primitive class MyValue19 { final int foo; MyValue19(int n) { @@ -864,7 +864,7 @@ static class MyObject20 { int x = 42; } - static final inline class MyValue20 { + static final primitive class MyValue20 { MyObject20 obj; MyValue20() { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnresolvedDefault.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnresolvedDefault.java index c15c183675f..7ed064aee7f 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnresolvedDefault.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnresolvedDefault.java @@ -30,7 +30,7 @@ public class TestUnresolvedDefault { - static inline class UnresolvedInline { + static primitive class UnresolvedInline { int x = 42; } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestWithfieldC1.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestWithfieldC1.java index 40abc9dd944..e8f0a5b4506 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestWithfieldC1.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestWithfieldC1.java @@ -98,7 +98,7 @@ static void set_foo_static_if_null(FooValue v) { } } - static inline class FooValue { + static primitive class FooValue { public int x = 0, y = 0; @ForceInline diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/hack/GetUnresolvedInlineFieldWrongSignature.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/hack/GetUnresolvedInlineFieldWrongSignature.java index 46fcc3a4129..0fb74afb081 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/hack/GetUnresolvedInlineFieldWrongSignature.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/hack/GetUnresolvedInlineFieldWrongSignature.java @@ -65,11 +65,11 @@ static class MyValue15Holder { MyValue15 v; } - static inline class MyValue16 { + static primitive class MyValue16 { int foo = 42; } - static inline class MyValue17 { + static primitive class MyValue17 { int foo = 42; } } diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestLoopStoreVector.java b/test/hotspot/jtreg/compiler/vectorapi/TestLoopStoreVector.java new file mode 100644 index 00000000000..02ae5684869 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestLoopStoreVector.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021, Huawei Technologies Co. Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.vectorapi; + +import jdk.incubator.vector.IntVector; +import jdk.incubator.vector.LongVector; +import jdk.incubator.vector.VectorSpecies; + +/* + * @test + * @bug 8260339 + * @summary StoreVectorNode is not considered with -XX:+OptimizeFill + * @modules jdk.incubator.vector + * + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+OptimizeFill compiler.vectorapi.TestLoopStoreVector + */ + +public class TestLoopStoreVector { + static final VectorSpecies SPECIESi = IntVector.SPECIES_PREFERRED; + static final VectorSpecies SPECIESl = LongVector.SPECIES_PREFERRED; + + static final int INVOC_COUNT = 5000; + static final int size = 64; + + static int[] ai = {20, 21, 02, 14, 83, 119, 101, 101, 116, 121, 44, 32, + 73, 32, 76, 79, 86, 69, 32, 89, 79, 85, 32, 102, 111, + 114, 101, 118, 101, 114, 33, 32, 32, 32, 45, 45, 32, + 32, 32, 66, 121, 32, 87, 97, 110, 103, 72, 117, 97, + 110, 103,46, 76, 105, 102, 101, 32, 105, 115, 32, 116, + 104, 101, 32}; + static long[] al = {102, 108, 111, 119, 101, 114, 32, 102, 111, 114, 32, + 119, 104, 105, 99, 104, 32, 108, 111, 118, 101, 32, + 105, 115, 32, 116, 104, 101, 32, 104, 111, 110, 101, + 121, 46, 32, 87, 101, 32, 119, 105, 108, 108, 32, 115, + 116, 105, 99, 107, 32, 116, 111, 103, 101, 116, 104, + 101, 114, 32, 33, 33, 33, 33, 32}; + + public static void testVectorCastL2I(long[] input, int[] output, VectorSpecies speciesl, VectorSpecies speciesi) { + LongVector av = LongVector.fromArray(speciesl, input, 0); + IntVector bv = (IntVector) av.castShape(speciesi, 0); + bv.intoArray(output, 0); + } + + public static int test0() { + for (int i = 0; i < 1000; i++) { + testVectorCastL2I(al, ai, SPECIESl, SPECIESi); + } + return 0; + } + + public static void main(String[] args) { + for (int i = 0; i < INVOC_COUNT; i++) { + test0(); + } + for (int i = 0; i < 64; i++) { + System.out.print(ai[i] + " "); + } + System.out.println(""); + } +} diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorRebracket128Test.java b/test/hotspot/jtreg/compiler/vectorapi/VectorRebracket128Test.java new file mode 100644 index 00000000000..6b266db08b6 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorRebracket128Test.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import jdk.incubator.vector.*; +import jdk.internal.vm.annotation.ForceInline; +import org.testng.Assert; +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.nio.ByteOrder; +import java.util.Arrays; +import java.util.List; +import java.util.function.IntFunction; +import java.util.function.IntUnaryOperator; +import jdk.incubator.vector.VectorShape; +import jdk.incubator.vector.VectorSpecies; +import jdk.internal.vm.annotation.ForceInline; + +/* + * @test + * @bug 8260473 + * @requires vm.gc.Z + * @modules jdk.incubator.vector + * @modules java.base/jdk.internal.vm.annotation + * @run testng/othervm -XX:CompileCommand=compileonly,jdk/incubator/vector/ByteVector.fromByteBuffer + * -XX:-TieredCompilation -XX:CICompilerCount=1 -XX:+UseZGC -Xbatch -Xmx256m VectorRebracket128Test + */ + +@Test +public class VectorRebracket128Test { + static final int INVOC_COUNT = Integer.getInteger("jtreg.compiler.vectorapi.vectorrebracket128test.loop-iterations", 1000); + static final int NUM_ITER = 200 * INVOC_COUNT; + + static final VectorSpecies ispec128 = IntVector.SPECIES_128; + static final VectorSpecies fspec128 = FloatVector.SPECIES_128; + static final VectorSpecies lspec128 = LongVector.SPECIES_128; + static final VectorSpecies dspec128 = DoubleVector.SPECIES_128; + static final VectorSpecies bspec128 = ByteVector.SPECIES_128; + static final VectorSpecies sspec128 = ShortVector.SPECIES_128; + + static IntFunction withToString(String s, IntFunction f) { + return new IntFunction() { + @Override + public T apply(int v) { + return f.apply(v); + } + + @Override + public String toString() { + return s; + } + }; + } + + interface ToByteF { + byte apply(int i); + } + + static byte[] fill_byte(int s , ToByteF f) { + return fill_byte(new byte[s], f); + } + + static byte[] fill_byte(byte[] a, ToByteF f) { + for (int i = 0; i < a.length; i++) { + a[i] = f.apply(i); + } + return a; + } + + static final List> BYTE_GENERATORS = List.of( + withToString("byte(i)", (int s) -> { + return fill_byte(s, i -> (byte)(i+1)); + }) + ); + + @DataProvider + public Object[][] byteUnaryOpProvider() { + return BYTE_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + static + void checkPartialResult(VectorSpecies a, VectorSpecies b, + byte[] input, byte[] output, byte[] expected, + int part, int origin) { + if (Arrays.equals(expected, output)) { + return; + } + int block; + block = Math.min(a.vectorByteSize(), b.vectorByteSize()); + + System.out.println("input: "+Arrays.toString(input)); + System.out.println("Failing with "+a+"->"+b+ + " (reinterpret)"+ + ", block=" + block + + ", part=" + part + + ", origin=" + origin); + System.out.println("expect: "+Arrays.toString(expected)); + System.out.println("output: "+Arrays.toString(output)); + Assert.assertEquals(expected, output); + } + + @ForceInline + static + void testVectorRebracket(VectorSpecies a, VectorSpecies b, byte[] input, byte[] output) { + Vector av = a.fromByteArray(input, 0, ByteOrder.nativeOrder()); + int block; + assert(input.length == output.length); + + block = Math.min(a.vectorByteSize(), b.vectorByteSize()); + if (false) + System.out.println("testing "+a+"->"+b+ + (false?" (lanewise)":" (reinterpret)")+ + ", block=" + block); + byte[] expected; + int origin; + + int part = 0; + Vector bv = av.reinterpretShape(b, part); + bv.intoByteArray(output, 0, ByteOrder.nativeOrder()); + // in-place copy, no resize + expected = input; + origin = 0; + checkPartialResult(a, b, input, output, expected, + part, origin); + + } + + @Test(dataProvider = "byteUnaryOpProvider") + static void testRebracket128(IntFunction fa) { + byte[] barr = fa.apply(128/Byte.SIZE); + byte[] bout = new byte[barr.length]; + for (int i = 0; i < NUM_ITER; i++) { + testVectorRebracket(bspec128, bspec128, barr, bout); + testVectorRebracket(bspec128, sspec128, barr, bout); + testVectorRebracket(bspec128, ispec128, barr, bout); + } + } + +} diff --git a/test/jdk/java/lang/ProcessBuilder/InheritIO/InheritIO.java b/test/hotspot/jtreg/compiler/vectorization/TestAbsCharVector.java similarity index 52% rename from test/jdk/java/lang/ProcessBuilder/InheritIO/InheritIO.java rename to test/hotspot/jtreg/compiler/vectorization/TestAbsCharVector.java index 83bb23d840c..33ff7725deb 100644 --- a/test/jdk/java/lang/ProcessBuilder/InheritIO/InheritIO.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestAbsCharVector.java @@ -1,5 +1,6 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Arm Limited. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,27 +22,42 @@ * questions. */ -import static java.lang.ProcessBuilder.Redirect.*; +/** + * @test + * @bug 8261022 + * @summary Test vectorization of Math.abs() with unsigned type + * @run main/othervm compiler.vectorization.TestAbsCharVector + */ + +package compiler.vectorization; + +public class TestAbsCharVector { -class InheritIO { + private static int SIZE = 60000; - public static class TestInheritIO { - public static void main(String args[]) throws Throwable { - int err = new ProcessBuilder(args).inheritIO().start().waitFor(); - System.err.print("exit value: " + err); - System.exit(err); + public static void main(String args[]) { + char[] a = new char[SIZE]; + char[] b = new char[SIZE]; + + for (int i = 0; i < SIZE; i++) { + a[i] = b[i] = (char) i; + } + + for (int i = 0; i < 20000; i++) { + arrayAbs(a); + } + + for (int i = 0; i < SIZE; i++) { + if (a[i] != b[i]) { + throw new RuntimeException("Broken!"); + } } } - public static class TestRedirectInherit { - public static void main(String args[]) throws Throwable { - int err = new ProcessBuilder(args) - .redirectInput(INHERIT) - .redirectOutput(INHERIT) - .redirectError(INHERIT) - .start().waitFor(); - System.err.print("exit value: " + err); - System.exit(err); + private static void arrayAbs(char[] arr) { + for (int i = 0; i < SIZE; i++) { + arr[i] = (char) Math.abs(arr[i]); } } } + diff --git a/test/hotspot/jtreg/compiler/whitebox/MakeMethodNotCompilableTest.java b/test/hotspot/jtreg/compiler/whitebox/MakeMethodNotCompilableTest.java index c0f70b55c37..59b0d36f5ef 100644 --- a/test/hotspot/jtreg/compiler/whitebox/MakeMethodNotCompilableTest.java +++ b/test/hotspot/jtreg/compiler/whitebox/MakeMethodNotCompilableTest.java @@ -201,7 +201,7 @@ private void testTier(int testedTier) { deoptimize(); } - if (!isCompilable(COMP_LEVEL_ANY)) { + if (!isCompilable(COMP_LEVEL_ANY) && TIERED_STOP_AT_LEVEL == COMP_LEVEL_FULL_OPTIMIZATION) { throw new RuntimeException(method + " must be compilable at 'CompLevel::CompLevel_any'" + ", if it is not compilable only at " + testedTier); diff --git a/test/hotspot/jtreg/gc/g1/TestLargePageUseForAuxMemory.java b/test/hotspot/jtreg/gc/g1/TestLargePageUseForAuxMemory.java index 67f4d0beeb2..685041921d3 100644 --- a/test/hotspot/jtreg/gc/g1/TestLargePageUseForAuxMemory.java +++ b/test/hotspot/jtreg/gc/g1/TestLargePageUseForAuxMemory.java @@ -49,9 +49,40 @@ public class TestLargePageUseForAuxMemory { static long smallPageSize; static long allocGranularity; + static boolean largePagesEnabled(OutputAnalyzer output) { + // The gc+init logging includes information about large pages. + String lp = output.firstMatch("Large Page Support: (\\w*)", 1); + return lp != null && lp.equals("Enabled"); + } + + static boolean largePagesAllocationFailure(OutputAnalyzer output, String pattern) { + // Check if there is a large page failure associated with the data structure + // being checked. In case of a large page allocation failure the output will + // include logs like this for the affected data structure: + // [0.048s][debug][gc,heap,coops] Reserve regular memory without large pages + // [0.048s][info ][pagesize ] Next Bitmap: ... page_size=4K ... + // + // The pattern passed in should match the second line. + String failureMatch = output.firstMatch("Reserve regular memory without large pages\\n.*" + pattern, 1); + if (failureMatch != null) { + return true; + } + return false; + } + static void checkSize(OutputAnalyzer output, long expectedSize, String pattern) { - String pageSizeStr = output.firstMatch(pattern, 1); + // First check the output for any large page allocation failure associated with + // the checked data structure. If we detect a failure then expect small pages. + if (largePagesAllocationFailure(output, pattern)) { + // This should only happen when we are expecting large pages + if (expectedSize == smallPageSize) { + throw new RuntimeException("Expected small page size when large page failure was detected"); + } + expectedSize = smallPageSize; + } + // Now check what page size is traced. + String pageSizeStr = output.firstMatch(pattern, 1); if (pageSizeStr == null) { output.reportDiagnosticSummary(); throw new RuntimeException("Match from '" + pattern + "' got 'null' expected: " + expectedSize); @@ -82,15 +113,21 @@ static void testVM(String what, long heapsize, boolean cardsShouldUseLargePages, pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", "-XX:G1HeapRegionSize=" + HEAP_REGION_SIZE, "-Xmx" + heapsize, - "-Xlog:pagesize", + "-Xlog:pagesize,gc+init,gc+heap+coops=debug", "-XX:+UseLargePages", "-XX:+IgnoreUnrecognizedVMOptions", // there is no ObjectAlignmentInBytes in 32 bit builds "-XX:ObjectAlignmentInBytes=8", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); - checkSmallTables(output, (cardsShouldUseLargePages ? largePageSize : smallPageSize)); - checkBitmaps(output, (bitmapShouldUseLargePages ? largePageSize : smallPageSize)); + // Only expect large page size if large pages are enabled. + if (largePagesEnabled(output)) { + checkSmallTables(output, (cardsShouldUseLargePages ? largePageSize : smallPageSize)); + checkBitmaps(output, (bitmapShouldUseLargePages ? largePageSize : smallPageSize)); + } else { + checkSmallTables(output, smallPageSize); + checkBitmaps(output, smallPageSize); + } output.shouldHaveExitValue(0); // Test with large page disabled. diff --git a/test/hotspot/jtreg/gc/parallel/TestDynShrinkHeap.java b/test/hotspot/jtreg/gc/parallel/TestDynShrinkHeap.java index 2d9478a2ebb..874087ba583 100644 --- a/test/hotspot/jtreg/gc/parallel/TestDynShrinkHeap.java +++ b/test/hotspot/jtreg/gc/parallel/TestDynShrinkHeap.java @@ -26,7 +26,7 @@ /** * @test TestDynShrinkHeap * @bug 8016479 - * @requires vm.gc.Parallel + * @requires vm.gc.Parallel & os.maxMemory > 1G * @summary Verify that the heap shrinks after full GC according to the current values of the Min/MaxHeapFreeRatio flags * @modules java.base/jdk.internal.misc * @modules jdk.management diff --git a/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java b/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java index 85d13bb2f46..aac4e3d02c9 100644 --- a/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java +++ b/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,9 +48,9 @@ public class TestReclaimStringsLeaksMemory { - // The amount of memory in kB reserved in the "Symbol" category that indicates a memory leak for + // The amount of memory in B reserved in the "Symbol" category that indicates a memory leak for // this test. - public static final int ReservedThreshold = 70000; + public static final int ReservedThreshold = 70000000; public static void main(String[] args) throws Exception { ArrayList baseargs = new ArrayList<>(Arrays.asList("-Xms256M", @@ -77,7 +77,7 @@ private static void verifySymbolMemoryUsageNotTooHigh(OutputAnalyzer output) thr } int reserved = Integer.parseInt(m.group(1)); - Asserts.assertLT(reserved, ReservedThreshold, "Reserved memory size is " + reserved + "KB which is greater than or equal to " + ReservedThreshold + "KB indicating a memory leak"); + Asserts.assertLT(reserved, ReservedThreshold, "Reserved memory size is " + reserved + "B which is greater than or equal to " + ReservedThreshold + "B indicating a memory leak"); output.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java b/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java index e52f8dabf61..a32075a7bfe 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/ArchiveRelocationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,8 @@ * @comment JDK-8231610 Relocate the CDS archive if it cannot be mapped to the requested address * @bug 8231610 * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes - * @build HelloRelocation - * @run driver ClassFileInstaller -jar hello.jar HelloRelocation HelloInlineClassApp HelloInlineClassApp$Point HelloInlineClassApp$Point$ref HelloInlineClassApp$Rectangle HelloInlineClassApp$Rectangle$ref + * @build Hello + * @run driver ClassFileInstaller -jar hello.jar Hello * @run driver ArchiveRelocationTest */ @@ -40,9 +40,8 @@ public class ArchiveRelocationTest { public static void main(String... args) throws Exception { try { - test(true, false); - test(false, true); - test(true, true); + test(false); + test(true); } catch (SkippedException s) { s.printStackTrace(); throw new RuntimeException("Archive mapping should always succeed after JDK-8231610 (did the machine run out of memory?)"); @@ -51,37 +50,29 @@ public static void main(String... args) throws Exception { static int caseCount = 0; - // dump_reloc - force relocation of archive during dump time? // run_reloc - force relocation of archive during run time? - static void test(boolean dump_reloc, boolean run_reloc) throws Exception { + // Note: relocation always happens during dumping. + static void test(boolean run_reloc) throws Exception { caseCount += 1; System.out.println("============================================================"); - System.out.println("case = " + caseCount + ", dump = " + dump_reloc - + ", run = " + run_reloc); + System.out.println("case = " + caseCount + ", run_reloc = " + run_reloc); System.out.println("============================================================"); - String appJar = ClassFileInstaller.getJarPath("hello.jar"); - String mainClass = "HelloRelocation"; + String mainClass = "Hello"; String forceRelocation = "-XX:ArchiveRelocationMode=1"; - String dumpRelocArg = dump_reloc ? forceRelocation : "-showversion"; String runRelocArg = run_reloc ? forceRelocation : "-showversion"; String logArg = "-Xlog:cds=debug,cds+reloc=debug"; String unlockArg = "-XX:+UnlockDiagnosticVMOptions"; String nmtArg = "-XX:NativeMemoryTracking=detail"; OutputAnalyzer out = TestCommon.dump(appJar, - TestCommon.list(mainClass, - "HelloInlineClassApp", - "HelloInlineClassApp$Point"), - unlockArg, dumpRelocArg, logArg, nmtArg); - if (dump_reloc) { - out.shouldContain("ArchiveRelocationMode == 1: always allocate class space at an alternative address"); - out.shouldContain("Relocating archive from"); - } + TestCommon.list(mainClass), + unlockArg, logArg, nmtArg); + out.shouldContain("Relocating archive from"); TestCommon.run("-cp", appJar, unlockArg, runRelocArg, logArg, mainClass) - .assertNormalExit(output -> { + .assertNormalExit(output -> { if (run_reloc) { output.shouldContain("Try to map archive(s) at an alternative address"); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/ExtraSymbols.java b/test/hotspot/jtreg/runtime/cds/appcds/ExtraSymbols.java index 27f0f6f936c..0f3caa4c36a 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/ExtraSymbols.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/ExtraSymbols.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,9 +74,12 @@ public static void main(String[] args) throws Exception { } static int numOfEntries(OutputAnalyzer output) { - String s = output.firstMatch("Number of entries : .*"); + // Look for this pattern: + // [4.661s][info][cds,hashtables] Shared symbol table stats -------- base: 0x0000000800000000 + // [4.661s][info][cds,hashtables] Number of entries : 50078 + String s = output.firstMatch("Shared symbol table stats[^\n]*\n[^\n]*Number of entries : .*"); String subs[] = s.split("[:]"); - int numEntries = Integer.parseInt(subs[1].trim()); + int numEntries = Integer.parseInt(subs[2].trim()); return numEntries; } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LotsOfClasses.java b/test/hotspot/jtreg/runtime/cds/appcds/LotsOfClasses.java index 9372e7aeed1..0f71c1ba389 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/LotsOfClasses.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/LotsOfClasses.java @@ -49,7 +49,7 @@ public static void main(String[] args) throws Exception { opts.addSuffix("-Xlog:hashtables"); opts.addSuffix("-Xmx500m"); opts.addSuffix("-Xlog:gc+region+cds"); - opts.addSuffix("-Xlog:gc+region=trace"); + opts.addSuffix("-Xlog:cds=debug"); // test detailed metadata info printing CDSTestUtils.createArchiveAndCheck(opts); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/AppendClasspath.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/AppendClasspath.java index 4a2d3d45da7..e593e602242 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/AppendClasspath.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/AppendClasspath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,8 +57,7 @@ private static void doTest(String topArchiveName) throws Exception { "-Xlog:cds+dynamic=debug", "-cp", appJar, "Hello") .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x"); + output.shouldContain("Written dynamic archive 0x"); }); // runtime with classpath containing the one used in dump time, diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java index 8eef29e1690..d890e60c869 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ArchiveConsistency.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -139,8 +139,7 @@ private static void doTest(String baseArchiveName, String topArchiveName) throws "-Xlog:cds+dynamic=debug", "-cp", appJar, mainClass) .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x"); + output.shouldContain("Written dynamic archive 0x"); }); File jsa = new File(topArchiveName); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ClassResolutionFailure.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ClassResolutionFailure.java index 666003fa78e..7179ec8832e 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ClassResolutionFailure.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ClassResolutionFailure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,8 +59,7 @@ private static void doTest(String topArchiveName) throws Exception { "-Xlog:class+load=trace", "-cp", appJar, mainClass) .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x"); + output.shouldContain("Written dynamic archive 0x"); }); run(topArchiveName, diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java index 858daccbd3b..218d2468076 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicArchiveRelocationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,27 +43,24 @@ public class DynamicArchiveRelocationTest extends DynamicArchiveTestBase { public static void main(String... args) throws Exception { try { - testOuter(false); - testOuter(true); + testOuter(); } catch (SkippedException s) { s.printStackTrace(); throw new RuntimeException("Archive mapping should always succeed after JDK-8231610 (did the machine run out of memory?)"); } } - static void testOuter(boolean dump_base_reloc) throws Exception { - testInner(dump_base_reloc, true, false); - testInner(dump_base_reloc, false, true); - testInner(dump_base_reloc, true, true); + static void testOuter() throws Exception { + testInner(true, false); + testInner(false, true); + testInner(true, true); } - static boolean dump_base_reloc, dump_top_reloc, run_reloc; + static boolean dump_top_reloc, run_reloc; - // dump_base_reloc - force relocation of archive when dumping base archive // dump_top_reloc - force relocation of archive when dumping top archive // run_reloc - force relocation of archive when running - static void testInner(boolean dump_base_reloc, boolean dump_top_reloc, boolean run_reloc) throws Exception { - DynamicArchiveRelocationTest.dump_base_reloc = dump_base_reloc; + static void testInner(boolean dump_top_reloc, boolean run_reloc) throws Exception { DynamicArchiveRelocationTest.dump_top_reloc = dump_top_reloc; DynamicArchiveRelocationTest.run_reloc = run_reloc; @@ -74,15 +71,14 @@ static void testInner(boolean dump_base_reloc, boolean dump_top_reloc, boolean r static void doTest() throws Exception { caseCount += 1; System.out.println("============================================================"); - System.out.println("case = " + caseCount + ", base = " + dump_base_reloc - + ", top = " + dump_top_reloc + System.out.println("case = " + caseCount + + ", top_reloc = " + dump_top_reloc + ", run = " + run_reloc); System.out.println("============================================================"); String appJar = ClassFileInstaller.getJarPath("hello.jar"); String mainClass = "HelloRelocation"; String forceRelocation = "-XX:ArchiveRelocationMode=1"; - String dumpBaseRelocArg = dump_base_reloc ? forceRelocation : "-showversion"; String dumpTopRelocArg = dump_top_reloc ? forceRelocation : "-showversion"; String runRelocArg = run_reloc ? forceRelocation : "-showversion"; String logArg = "-Xlog:cds=debug,cds+reloc=debug"; @@ -91,17 +87,18 @@ static void doTest() throws Exception { String topArchiveName = getNewArchiveName("top"); String runtimeMsg = "Try to map archive(s) at an alternative address"; + String runtimeRelocMsg = "runtime archive relocation start"; String unmapPrefix = ".*Unmapping region #3 at base 0x.*"; String unmapPattern = unmapPrefix + "(Bitmap)"; + String archiveRelocPattern = ".*ArchiveRelocationMode == 1.*"; + String unmapRgn1Pattern = ".*Unmapping region #1 at base 0x.*"; + String unmapRgn0Pattern = ".*Unmapping region #0 at base 0x.*(MiscCode)"; String unlockArg = "-XX:+UnlockDiagnosticVMOptions"; // (1) Dump base archive (static) - OutputAnalyzer out = TestCommon.dumpBaseArchive(baseArchiveName, unlockArg, dumpBaseRelocArg, logArg); - if (dump_base_reloc) { - out.shouldContain("ArchiveRelocationMode == 1: always allocate class space at an alternative address"); - out.shouldContain("Relocating archive from"); - } + OutputAnalyzer out = TestCommon.dumpBaseArchive(baseArchiveName, unlockArg, logArg); + out.shouldContain("Relocating archive from"); // (2) Dump top archive (dynamic) @@ -123,12 +120,21 @@ static void doTest() throws Exception { "-cp", appJar, mainClass) .assertNormalExit(output -> { if (run_reloc) { - output.shouldContain(runtimeMsg) - // Check that there are two of the following lines in - // the output. One for static archive and one for - // dynamic archive: - // Unmapping region #3 at base 0x (Bitmap) - .shouldMatchByLine(unmapPrefix, "Hello World", unmapPattern); + output.shouldContain(runtimeMsg); + try { + output.shouldContain(runtimeRelocMsg) + // Check that there are two of the following lines in + // the output. One for static archive and one for + // dynamic archive: + // Unmapping region #3 at base 0x (Bitmap) + .shouldMatchByLine(unmapPrefix, "Hello World", unmapPattern); + } catch(java.lang.RuntimeException ex) { + // On Windows, sometimes the OS picks the same archive + // base address even with ArchiveRelcationMode=1. In + // this case, runtime relocation won't happen. Checking + // for "Unmapping region #0" messages instead. + output.shouldMatchByLine(archiveRelocPattern, unmapRgn1Pattern, unmapRgn0Pattern); + } } }); } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicLotsOfClasses.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicLotsOfClasses.java index 81c00bb054a..202d00f889c 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicLotsOfClasses.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DynamicLotsOfClasses.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,13 +75,12 @@ private static void doTest(String topArchiveName) throws Exception { "ALL-SYSTEM", "-Xlog:hashtables", "-Xmx500m", - "-Xlog:cds,cds+dynamic", + "-Xlog:cds=debug", // test detailed metadata info printing + "-Xlog:cds+dynamic=info", bootClassPath, "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", "-cp", appJar, mainClass, classList) - .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x"); - }); + .assertNormalExit("Written dynamic archive 0x", + "Detailed metadata info"); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamic.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamic.java index 2a71937460e..3af7e1a0ca8 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamic.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,8 +65,7 @@ private static void doTest(String baseArchiveName, String topArchiveName) throws "-Xlog:cds+dynamic=debug", "-cp", appJar, mainClass) .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x"); + output.shouldContain("Written dynamic archive 0x"); }); run2(baseArchiveName, topArchiveName, "-Xlog:class+load", diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicCustom.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicCustom.java index 69e44f1e419..1b0424c676a 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicCustom.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicCustom.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,8 +62,7 @@ private static void testDefaultBase() throws Exception { "-cp", appJar, mainAppClass, customJarPath, "false", "false") .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x") + output.shouldContain("Written dynamic archive 0x") .shouldNotContain("klasses.*=.*CustomLoadee") .shouldHaveExitValue(0); }); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicCustomUnload.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicCustomUnload.java index 1f8d907434c..89e5e375f31 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicCustomUnload.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicCustomUnload.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * 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,8 +70,7 @@ private static void doTest(String topArchiveName) throws Exception { "-cp", appJar, mainAppClass, customJarPath, "true", "false") .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x") + output.shouldContain("Written dynamic archive 0x") .shouldNotContain("klasses.*=.*CustomLoadee") // Fixme -- use a better way to decide if a class has been archived .shouldHaveExitValue(0); }); diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicInlineClass.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicInlineClass.java index 31706b6f1f0..435b5912302 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicInlineClass.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/HelloDynamicInlineClass.java @@ -62,8 +62,7 @@ private static void doTest(String baseArchiveName, String topArchiveName) throws "-Xlog:cds+dynamic=debug", "-cp", appJar, mainClass) .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x"); + output.shouldContain("Written dynamic archive 0x"); }); run2(baseArchiveName, topArchiveName, "-Xlog:class+load", diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/JITInteraction.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/JITInteraction.java index 09cfbfcec08..fed77538654 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/JITInteraction.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/JITInteraction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,8 +57,7 @@ private static void doTest(String topArchiveName) throws Exception { "-XX:+PrintCompilation", "-cp", appJar, mainClass) .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x"); + output.shouldContain("Written dynamic archive 0x"); }); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaInBaseArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaInBaseArchive.java index 8abab036d51..f4dc22a4e1e 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaInBaseArchive.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaInBaseArchive.java @@ -74,8 +74,7 @@ private static void doTest(String baseArchiveName, String topArchiveName) throws "-Xlog:class+load,cds,cds+dynamic=debug", "-cp", appJar, mainClass) .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x"); + output.shouldContain("Written dynamic archive 0x"); }); run2(baseArchiveName, topArchiveName, diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MainModuleOnly.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MainModuleOnly.java index 1f7361333c8..ed55e430b50 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MainModuleOnly.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MainModuleOnly.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -106,8 +106,7 @@ public static void doTest(String topArchiveName) throws Exception { "--module-path", moduleDir.toString(), "-m", TEST_MODULE1) .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x"); + output.shouldContain("Written dynamic archive 0x"); }); // run with the archive using the same command line as in dump time. diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MismatchedBaseArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MismatchedBaseArchive.java index a0d03ba80d1..fdb2ed072f4 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MismatchedBaseArchive.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MismatchedBaseArchive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,8 +72,7 @@ private static void doTest(String baseArchiveName, String topArchiveName) throws "-Xlog:cds+dynamic=debug", "-cp", appJar, mainClass) .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x"); + output.shouldContain("Written dynamic archive 0x"); }); run2(helloBaseArchive, topArchiveName, diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MissingArchive.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MissingArchive.java index eb75c1322e6..90e0cb8db89 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MissingArchive.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/MissingArchive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,8 +65,7 @@ static void test(String args[]) throws Exception { "-Xlog:cds+dynamic=debug", "-cp", appJar, mainClass) .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x"); + output.shouldContain("Written dynamic archive 0x"); }); // Use -Xshare:auto so top archive can fail after base archive has succeeded, diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/SharedArchiveFileOption.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/SharedArchiveFileOption.java index cfe3791006a..1324fb204f0 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/SharedArchiveFileOption.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/SharedArchiveFileOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * 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,8 +83,7 @@ private static void doTest(String baseArchiveName, String topArchiveName) throws "-Xlog:cds+dynamic=debug", "-cp", appJar, mainClass) .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x"); + output.shouldContain("Written dynamic archive 0x"); }); // same archive file specified for -XX:SharedArchiveFile and -XX:ArchiveClassesAtExit diff --git a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/UnusedCPDuringDump.java b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/UnusedCPDuringDump.java index da79d62a4d8..455eb19c668 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/UnusedCPDuringDump.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/UnusedCPDuringDump.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,8 +66,7 @@ private static void doTest(String topArchiveName) throws Exception { "-cp", dir.getPath(), "Hello") .assertNormalExit(output -> { - output.shouldContain("Buffer-space to target-space delta") - .shouldContain("Written dynamic archive 0x"); + output.shouldContain("Written dynamic archive 0x"); }); // Running with -cp different from dumping. It should be fine because diff --git a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/HelloInlineClassApp.java b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/HelloInlineClassApp.java index e04356fde17..dfbc3d89c66 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/HelloInlineClassApp.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/HelloInlineClassApp.java @@ -23,7 +23,7 @@ */ public class HelloInlineClassApp { - static inline class Point { + static primitive class Point { int x, y; public String toString() { @@ -48,7 +48,7 @@ Point add(Point p1, int x2, int y2, Point p3) { } } - static inline class Rectangle { + static primitive class Rectangle { Point p0 = new Point(0,0); Point p1 = new Point(1,1); } @@ -104,4 +104,4 @@ public static void main(String[] args) throws Exception { } } -} \ No newline at end of file +} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/Point.java b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/Point.java index c1df8c24c58..e75632a7228 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/test-classes/Point.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/test-classes/Point.java @@ -22,7 +22,7 @@ * */ -public inline class Point { +public primitive class Point { int i = 0, j = 0; public String msg() { diff --git a/test/hotspot/jtreg/runtime/logging/ProtectionDomainVerificationTest.java b/test/hotspot/jtreg/runtime/logging/ProtectionDomainVerificationTest.java index 9c15817e1ac..88151e77f74 100644 --- a/test/hotspot/jtreg/runtime/logging/ProtectionDomainVerificationTest.java +++ b/test/hotspot/jtreg/runtime/logging/ProtectionDomainVerificationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,22 +40,38 @@ public static void main(String... args) throws Exception { // -Xlog:protectiondomain=trace ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:protectiondomain=trace", "-Xmx128m", - Hello.class.getName()); - OutputAnalyzer out = new OutputAnalyzer(pb.start()); - out.shouldContain("[protectiondomain] Checking package access"); - out.shouldContain("[protectiondomain] pd set count = #"); + Hello.class.getName(), "security_manager"); + new OutputAnalyzer(pb.start()) + .shouldHaveExitValue(0) + .shouldContain("[protectiondomain] Checking package access") + .shouldContain("[protectiondomain] pd set count = #"); // -Xlog:protectiondomain=debug pb = ProcessTools.createJavaProcessBuilder("-Xlog:protectiondomain=debug", "-Xmx128m", - Hello.class.getName()); - out = new OutputAnalyzer(pb.start()); - out.shouldContain("[protectiondomain] Checking package access"); - out.shouldNotContain("pd set count = #"); + Hello.class.getName(), "security_manager"); + new OutputAnalyzer(pb.start()) + .shouldHaveExitValue(0) + .shouldContain("[protectiondomain] Checking package access") + .shouldNotContain("pd set count = #"); + + // -Xlog:protectiondomain=debug + pb = ProcessTools.createJavaProcessBuilder("-Xlog:protectiondomain=trace", + "-Xmx128m", + "-Djava.security.manager=disallow", + Hello.class.getName()); + new OutputAnalyzer(pb.start()) + .shouldHaveExitValue(0) + .shouldNotContain("[protectiondomain] Checking package access") + .shouldNotContain("pd set count = #"); } public static class Hello { public static void main(String[] args) { + if (args.length == 1) { + // Need a security manager to trigger logging. + System.setSecurityManager(new SecurityManager()); + } System.out.print("Hello!"); } } diff --git a/test/hotspot/jtreg/runtime/valhalla/TypeRestrictions/PointBox.java b/test/hotspot/jtreg/runtime/valhalla/TypeRestrictions/PointBox.java index 5e8532705aa..089de4c6860 100644 --- a/test/hotspot/jtreg/runtime/valhalla/TypeRestrictions/PointBox.java +++ b/test/hotspot/jtreg/runtime/valhalla/TypeRestrictions/PointBox.java @@ -33,14 +33,14 @@ class PointBox { @RestrictedType("Qruntime/valhalla/typerestrictions/PointBox$Point;") static public Object p71; - static inline class Point { + static primitive class Point { public double x; public double y; public Point(double x, double y) { this.x = x; this.y = y; } } - static inline class Rec { + static primitive class Rec { @RestrictedType("Qruntime/valhalla/typerestrictions/PointBox$Point;") public Point.ref p37; diff --git a/test/hotspot/jtreg/runtime/valhalla/TypeRestrictions/SimpleTest.java b/test/hotspot/jtreg/runtime/valhalla/TypeRestrictions/SimpleTest.java index dbf013d1c0a..ee2c408262d 100644 --- a/test/hotspot/jtreg/runtime/valhalla/TypeRestrictions/SimpleTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/TypeRestrictions/SimpleTest.java @@ -34,7 +34,7 @@ */ public class SimpleTest { - static inline class Point { + static primitive class Point { public double x; public double y; public Point(double x, double y) { this.x = x; this.y = y; } diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CheckcastTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CheckcastTest.java index b13e9d15bc4..8516de1a3ee 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CheckcastTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CheckcastTest.java @@ -36,7 +36,7 @@ public class CheckcastTest { - static inline class Point { + static primitive class Point { int x; int y; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CircularityTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CircularityTest.java index 8a4edc49444..a2108138e3f 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CircularityTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CircularityTest.java @@ -37,27 +37,27 @@ public class CircularityTest { static boolean b = true; static int counter = 0; - static inline class A { + static primitive class A { static B b; static C c; int i = 0; } - static inline class B { + static primitive class B { static { Asserts.assertNotNull(A.c, "Should have returned C's default value"); } int i = 0; } - static inline class C { + static primitive class C { int i; public C(int i) { this.i = i; } } - static inline class D { + static primitive class D { static C c; int i = 0; static { @@ -68,25 +68,25 @@ static inline class D { } } - static inline class E { + static primitive class E { static F f; static C c; int i = 0; } - static inline class F { + static primitive class F { int i = 0; static { E.c = new C(5); } } - static inline class G { + static primitive class G { static H h; int i = 0; } - static inline class H { + static primitive class H { int i = 0; static { if (CircularityTest.b) { @@ -96,13 +96,13 @@ static inline class H { } } - static inline class I { + static primitive class I { static J j; static H h; int i = 0; } - static inline class J { + static primitive class J { int i = 0; static { CircularityTest.counter = 1; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CreationErrorTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CreationErrorTest.java index 3028ad39a51..629f21287ac 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CreationErrorTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/CreationErrorTest.java @@ -56,7 +56,7 @@ public class CreationErrorTest { - static inline class InlineClass { + static primitive class InlineClass { int i = 0; } diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/EmptyInlineTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/EmptyInlineTest.java index 0a767d4860b..7fd4b2b6811 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/EmptyInlineTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/EmptyInlineTest.java @@ -37,13 +37,13 @@ public class EmptyInlineTest { - static inline class EmptyInline { + static primitive class EmptyInline { public boolean isEmpty() { return true; } } - static inline class EmptyField { + static primitive class EmptyField { EmptyInline empty; EmptyField() { diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Ifacmp.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Ifacmp.java index 07780f4a550..e73071cf522 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Ifacmp.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Ifacmp.java @@ -37,11 +37,11 @@ */ public class Ifacmp { - static inline class MyValue { + static primitive class MyValue { int value; public MyValue(int v) { this.value = v; } }; - static inline class MyValue2 { + static primitive class MyValue2 { int value; public MyValue2(int v) { this.value = v; } }; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineOops.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineOops.java index 7fd3ca28b37..c4dbf159f20 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineOops.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineOops.java @@ -205,7 +205,7 @@ static class Couple { public Person otherPerson; } - static final inline class Composition { + static final primitive class Composition { public final Person onePerson; public final Person otherPerson; @@ -298,14 +298,14 @@ public static void testOopMaps() { // Sanity check, FixMe need more test cases objects = testFrameOops(couple); - //assertTrue(objects.length == 5, "Number of frame oops incorrect = " + objects.length); - //assertTrue(objects[0] == couple, "Bad oop 0"); - //assertTrue(objects[1] == fn1, "Bad oop 1"); - //assertTrue(objects[2] == ln1, "Bad oop 2"); - //assertTrue(objects[3] == TEST_STRING1, "Bad oop 3"); - //assertTrue(objects[4] == TEST_STRING2, "Bad oop 4"); + assertTrue(objects.length == 5, "Number of frame oops incorrect = " + objects.length); + assertTrue(objects[0] == couple, "Bad oop 0"); + assertTrue(objects[1] == fn1, "Bad oop 1"); + assertTrue(objects[2] == ln1, "Bad oop 2"); + assertTrue(objects[3] == TEST_STRING1, "Bad oop 3"); + assertTrue(objects[4] == TEST_STRING2, "Bad oop 4"); - //testFrameOopsVBytecodes(); + testFrameOopsVBytecodes(); } static final String GET_OOP_MAP_NAME = "getOopMap"; @@ -601,7 +601,7 @@ static void validatePeople(Object array) { // Various field layouts...sanity testing, see MVTCombo testing for full-set - static final inline class ObjectValue { + static final primitive class ObjectValue { final Object object; private ObjectValue(Object obj) { @@ -635,7 +635,7 @@ static class Bar extends Foo { String otherStuff; } - public static final inline class FooValue { + public static final primitive class FooValue { public final int id; public final String name; public final String description; @@ -733,7 +733,7 @@ static class BarWithValue { String otherStuff; } - static final inline class BarValue { + static final primitive class BarValue { final FooValue foo; final long extendedId; final String moreNotes; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeArray.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeArray.java index a91edf591f4..6535d264257 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeArray.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeArray.java @@ -244,7 +244,7 @@ void testReflectArray() { assertEquals(x, 1, "Bad Point Value"); } - static final inline class MyInt implements Comparable { + static final primitive class MyInt implements Comparable { final int value; private MyInt() { this(0); } @@ -277,7 +277,7 @@ static interface SomeSecondaryType { default String hi() { return "Hi"; } } - static final inline class MyOtherInt implements SomeSecondaryType { + static final primitive class MyOtherInt implements SomeSecondaryType { final int value; private MyOtherInt() { value = 0; } } @@ -465,7 +465,7 @@ void testMixedLayoutArrays() { } catch (NullPointerException npe) {} } - static final inline class MyPoint { + static final primitive class MyPoint { final MyInt x; final MyInt y; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeCreation.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeCreation.java index 99ac05017e5..2bd817385d9 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeCreation.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeCreation.java @@ -73,7 +73,7 @@ void testPerson() { Asserts.assertEquals(person.getLastName(), "Smith", "Last name incorrect"); } - static final inline class StaticSelf { + static final primitive class StaticSelf { static final StaticSelf.ref DEFAULT = create(0); final int f1; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeDensity.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeDensity.java index 4bfccd5e874..c922337b40e 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeDensity.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeDensity.java @@ -73,7 +73,7 @@ interface LocalTime { interface LocalDateTime extends LocalDate, LocalTime {} - static final inline class LocalDateValue implements LocalDate { + static final primitive class LocalDateValue implements LocalDate { final int year; final short month; final short day; @@ -97,7 +97,7 @@ public static LocalDateValue create(int year, short month, short day) { } } - static final inline class LocalTimeValue implements LocalTime { + static final primitive class LocalTimeValue implements LocalTime { final byte hour; final byte minute; final byte second; @@ -125,7 +125,7 @@ public static LocalTimeValue create(byte hour, byte minute, byte second, int nan } } - static final inline class LocalDateTimeValue implements LocalDateTime { + static final primitive class LocalDateTimeValue implements LocalDateTime { final LocalDateValue date; final LocalTimeValue time; @@ -233,10 +233,10 @@ public void ensureArraySizeWin() { Asserts.assertLessThan(flatArraySize, objectArraySize, "Flat array accounts for more heap than object array + elements !"); } - static inline class MyByte { byte v = 0; } - static inline class MyShort { short v = 0; } - static inline class MyInt { int v = 0; } - static inline class MyLong { long v = 0; } + static primitive class MyByte { byte v = 0; } + static primitive class MyShort { short v = 0; } + static primitive class MyInt { int v = 0; } + static primitive class MyLong { long v = 0; } void assertArraySameSize(Object a, Object b, int nofElements) { long aSize = WHITE_BOX.getObjectSize(a); @@ -287,11 +287,11 @@ public void testPrimitiveArraySizesSame() { testLongArraySizesSame(testSizes); } - static inline class bbValue { byte b = 0; byte b2 = 0;} - static inline class bsValue { byte b = 0; short s = 0;} - static inline class siValue { short s = 0; int i = 0;} - static inline class ssiValue { short s = 0; short s2 = 0; int i = 0;} - static inline class blValue { byte b = 0; long l = 0; } + static primitive class bbValue { byte b = 0; byte b2 = 0;} + static primitive class bsValue { byte b = 0; short s = 0;} + static primitive class siValue { short s = 0; int i = 0;} + static primitive class ssiValue { short s = 0; short s2 = 0; int i = 0;} + static primitive class blValue { byte b = 0; long l = 0; } // Expect aligned array addressing to nearest pow2 void testAlignedSize() { diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineWithJni.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineWithJni.java index c49ce244a25..80c12351c3a 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineWithJni.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineWithJni.java @@ -29,7 +29,7 @@ * @run main/othervm/native -Xint runtime.valhalla.inlinetypes.InlineWithJni * @run main/othervm/native -Xcomp runtime.valhalla.inlinetypes.InlineWithJni */ -public inline final class InlineWithJni { +public primitive final class InlineWithJni { static { System.loadLibrary("InlineWithJni"); diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/IntValue.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/IntValue.java index 06e070799f4..5981fba36da 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/IntValue.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/IntValue.java @@ -23,7 +23,7 @@ package runtime.valhalla.inlinetypes; -public inline class IntValue { +public primitive class IntValue { int val; public IntValue() { this(0); } public IntValue(int v) { val = v; } diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/JumboInline.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/JumboInline.java index b45672beb92..854b6423ff0 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/JumboInline.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/JumboInline.java @@ -22,7 +22,7 @@ */ package runtime.valhalla.inlinetypes; -public inline final class JumboInline { +public primitive final class JumboInline { final long l0; final long l1; final long l2; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Long8Inline.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Long8Inline.java index 3bd2b4d899e..f85130d0be9 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Long8Inline.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Long8Inline.java @@ -25,7 +25,7 @@ import jdk.test.lib.Asserts; -public final inline class Long8Inline { +public final primitive class Long8Inline { final long longField1; final long longField2; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/MultiANewArrayTest/Element1.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/MultiANewArrayTest/Element1.java index cc097843fe4..a1366e4673f 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/MultiANewArrayTest/Element1.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/MultiANewArrayTest/Element1.java @@ -22,6 +22,6 @@ * */ -public inline class Element1 { +public primitive class Element1 { int i=0,j=0; } diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/ObjectMethods.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/ObjectMethods.java index 22dd64e3d68..7ee2ed966b9 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/ObjectMethods.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/ObjectMethods.java @@ -215,7 +215,7 @@ static void checkNotify(Object val) { } } - static final inline class MyInt { + static final primitive class MyInt { final int value; private MyInt() { value = 0; } public static MyInt create(int v) { diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Person.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Person.java index 80d3eda9b36..8a78a588964 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Person.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Person.java @@ -23,7 +23,7 @@ package runtime.valhalla.inlinetypes; -public final inline class Person { +public final primitive class Person { final int id; final String firstName; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Point.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Point.java index c2aedcf63de..e2b15a9a78e 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Point.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Point.java @@ -22,7 +22,7 @@ */ package runtime.valhalla.inlinetypes; -public inline final class Point { +public primitive final class Point { final int x; final int y; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/QuickeningTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/QuickeningTest.java index 76bee43ffc3..65ed50ae392 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/QuickeningTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/QuickeningTest.java @@ -57,7 +57,7 @@ static class Child extends Parent { public void setFj2(JumboInline j) { fj2 = j; } } - static final inline class Value { + static final primitive class Value { final Point.ref nfp; /* Not flattenable inline field */ final Point fp; /* Flattenable and flattened inline field */ final JumboInline fj; /* Flattenable not flattened inline field */ diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/StaticFieldsTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/StaticFieldsTest.java index bc2d974de26..35959943258 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/StaticFieldsTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/StaticFieldsTest.java @@ -38,7 +38,7 @@ public class StaticFieldsTest { // ClassA and ClassB have a simple cycle in their static fields, but they should // be able to load and initialize themselves successfully. Access to these // static fields after their initialization should return the default value. - static inline class ClassA { + static primitive class ClassA { static ClassB b; public int i; @@ -47,7 +47,7 @@ public ClassA() { } } - static inline class ClassB { + static primitive class ClassB { static ClassA a; public int i; @@ -59,7 +59,7 @@ public ClassB() { // ClassC has a reference to itself in its static field, but it should be able // to initialize itelf successfully. Access to this static field after initialization // should return the default value. - static inline class ClassC { + static primitive class ClassC { static ClassC c; int i; @@ -73,7 +73,7 @@ public ClassC() { // read these static fields during their initialization, the value read from // these fields should be the default value. Both classes should initialize // successfully. - static inline class ClassD { + static primitive class ClassD { static ClassE e; int i; @@ -86,7 +86,7 @@ public ClassD() { } } - static inline class ClassE { + static primitive class ClassE { static ClassD d; int i; @@ -102,7 +102,7 @@ public ClassE() { // ClassF and ClassG have circular references in their static fields, and they // create new instances of each other type to initialize these static fields // during their initialization. Both classes should initialize successfully. - static inline class ClassF { + static primitive class ClassF { static ClassG g; int i; @@ -116,7 +116,7 @@ static inline class ClassF { } } - static inline class ClassG { + static primitive class ClassG { static ClassF f; int i; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Test8186715.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Test8186715.java index 4dab0563c32..d73abcc04e6 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Test8186715.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/Test8186715.java @@ -43,7 +43,7 @@ public static void main(String[] args) { } } -inline final class MyValueType { +primitive final class MyValueType { final int i; final int j; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestFieldNullability.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestFieldNullability.java index 673f229d482..1a415ef17f4 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestFieldNullability.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestFieldNullability.java @@ -34,7 +34,7 @@ import jdk.test.lib.Asserts; public class TestFieldNullability { - static inline class MyValue { + static primitive class MyValue { int x; public MyValue() { @@ -42,7 +42,7 @@ public MyValue() { } } - static inline class MyBigValue { + static primitive class MyBigValue { long l0, l1, l2, l3, l4, l5, l6, l7, l8, l9; long l10, l11, l12, l13, l14, l15, l16, l17, l18, l19; @@ -52,7 +52,7 @@ public MyBigValue() { } } - static inline class TestInlineType { + static primitive class TestInlineType { final MyValue.ref nullableField; final MyValue nullfreeField; // flattened final MyValue.ref nullField; // src of null diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestJNIArrays.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestJNIArrays.java index 4fa78d52a90..7fa6f694429 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestJNIArrays.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestJNIArrays.java @@ -63,7 +63,7 @@ public class TestJNIArrays { System.loadLibrary("TestJNIArrays"); } - static inline class IntInt { + static primitive class IntInt { int i0; int i1; @@ -83,7 +83,7 @@ public int compare(IntInt.ref a, IntInt.ref b) { } } - static inline class Containee { + static primitive class Containee { float f; short s; @@ -93,7 +93,7 @@ static inline class Containee { } } - static inline class Container { + static primitive class Container { double d; Containee c; byte b; @@ -111,7 +111,7 @@ Container setc(Containee c) { } - static inline class LongLongLongLong { + static primitive class LongLongLongLong { long l0, l1, l2, l3; public LongLongLongLong(long l0, long l1, long l2, long l3) { @@ -122,14 +122,14 @@ public LongLongLongLong(long l0, long l1, long l2, long l3) { } } - static inline class BigValue { + static primitive class BigValue { long l0 = 0, l1 = 0, l2 = 0, l3 = 0, l4 = 0, l5 = 0, l6 = 0, l7 = 0, l8 = 0, l9 = 0; long l10 = 0, l11 = 0, l12 = 0, l13 = 0, l14 = 0, l15 = 0, l16 = 0, l17 = 0, l18 = 0, l19 = 0; long l20 = 0, l21 = 0, l22 = 0, l23 = 0, l24 = 0, l25 = 0, l26 = 0, l27 = 0, l28 = 0, l29 = 0; long l30 = 0, l31 = 0, l32 = 0, l33 = 0, l34 = 0, l35 = 0, l36 = 0, l37 = 0, l38 = 0, l39 = 0; } - static inline class InlineWithOops { + static primitive class InlineWithOops { String s = "bonjour"; int i = 0; Containee c = new Containee(2.3f, (short)4); diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestJNIIsSameObject.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestJNIIsSameObject.java index 790d7e1188b..4d1dda5e7ed 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestJNIIsSameObject.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestJNIIsSameObject.java @@ -34,7 +34,7 @@ * @run main/othervm/native TestJNIIsSameObject */ public class TestJNIIsSameObject { - static inline class Value { + static primitive class Value { int i; public Value(int i) { diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue1.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue1.java index dee7b5ba964..bddbe580119 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue1.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue1.java @@ -28,7 +28,7 @@ final class ContainerValue1 { TestValue1[] inlineArray; } -public inline final class TestValue1 { +public primitive final class TestValue1 { static TestValue1.ref staticValue = getInstance(); diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue2.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue2.java index 81c28716768..729930c4b72 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue2.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue2.java @@ -28,7 +28,7 @@ final class ContainerValue2 { TestValue2[] valueArray; } -public inline final class TestValue2 { +public primitive final class TestValue2 { static TestValue2.ref staticValue = getInstance(); final long l; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue3.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue3.java index 602c9090c6d..544d78f7f26 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue3.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue3.java @@ -28,7 +28,7 @@ final class ContainerValue3 { TestValue3[] valueArray; } -public inline final class TestValue3 { +public primitive final class TestValue3 { static TestValue3.ref staticValue = getInstance(); diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue4.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue4.java index a13b92f2d03..25f42f9f3f5 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue4.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/TestValue4.java @@ -30,7 +30,7 @@ final class ContainerValue4 { TestValue4[] valueArray; } -public inline final class TestValue4 { +public primitive final class TestValue4 { static TestValue4.ref staticValue = getInstance(); diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/UnsafeTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/UnsafeTest.java index 7d83017354b..f3b3b38f956 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/UnsafeTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/UnsafeTest.java @@ -42,7 +42,7 @@ public class UnsafeTest { static final Unsafe U = Unsafe.getUnsafe(); - static inline class Value1 { + static primitive class Value1 { Point point; Point[] array; Value1(Point p, Point... points) { @@ -51,7 +51,7 @@ static inline class Value1 { } } - static inline class Value2 { + static primitive class Value2 { int i; Value1 v; @@ -61,7 +61,7 @@ static inline class Value2 { } } - static inline class Value3 { + static primitive class Value3 { Object o; Value2 v; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VDefaultTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VDefaultTest.java index 46f44ce3792..116a0fd7e92 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VDefaultTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VDefaultTest.java @@ -37,7 +37,7 @@ public class VDefaultTest { - static inline final class Point { + static primitive final class Point { final int x; final int y; @@ -52,7 +52,7 @@ static Point make() { } } - static inline final class Value { + static primitive final class Value { final char c; final byte b; final short s; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VWithFieldTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VWithFieldTest.java index 699b966ac18..5117bc09097 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VWithFieldTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VWithFieldTest.java @@ -37,7 +37,7 @@ public class VWithFieldTest { - static inline final class Point { + static primitive final class Point { final private int x; final private int y; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/ValueTearing.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/ValueTearing.java index 69f5fedceff..727730eb63d 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/ValueTearing.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/ValueTearing.java @@ -111,7 +111,7 @@ public static void main(String[] args) throws Exception { } // A normally tearable inline value. - static inline class TPoint { + static primitive class TPoint { TPoint(long x, long y) { this.x = x; this.y = y; } final long x, y; public String toString() { return String.format("(%d,%d)", x, y); } @@ -176,7 +176,7 @@ public String toString() { interface NT extends NonTearable { } // A hardened, non-tearable version of TPoint. - static inline class NTPoint implements NT { + static primitive class NTPoint implements NT { NTPoint(long x, long y) { this.x = x; this.y = y; } final long x, y; public String toString() { return String.format("(%d,%d)", x, y); } diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VarArgsArray.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VarArgsArray.java index 285889dffc3..a7238248702 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VarArgsArray.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VarArgsArray.java @@ -157,7 +157,7 @@ public static void main(String[] args) throws Throwable { new VarArgsArray().test(); } - inline class MyInt { + primitive class MyInt { int value; public MyInt() { this(0); } public MyInt(int v) { this.value = v; } diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VolatileTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VolatileTest.java index 1ffbf87e65c..6e508092d7c 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VolatileTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/VolatileTest.java @@ -39,7 +39,7 @@ public class VolatileTest { static final Unsafe U = Unsafe.getUnsafe(); - static inline class MyValue { + static primitive class MyValue { int i = 0; int j = 0; } diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/WithFieldAccessorTest.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/WithFieldAccessorTest.java index e27ef7fc70f..89a82a1d209 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/WithFieldAccessorTest.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/WithFieldAccessorTest.java @@ -33,7 +33,7 @@ // access to public, protected, and private final fields in an inline type. public class WithFieldAccessorTest { - public static final inline class V { + public static final primitive class V { public final char c; protected final long l; private final int i; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/identityObject/InlineType.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/identityObject/InlineType.java index 45b01e80554..da712a96068 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/identityObject/InlineType.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/identityObject/InlineType.java @@ -1,3 +1,3 @@ -public inline class InlineType { +public primitive class InlineType { int i = 0; } diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/VTAssignability.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/VTAssignability.java index 29314153b69..aadb65d127b 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/VTAssignability.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/VTAssignability.java @@ -33,7 +33,7 @@ // interface II { } -public inline final class VTAssignability implements II { +public primitive final class VTAssignability implements II { final int x; final int y; diff --git a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/VTMonitor.java b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/VTMonitor.java index 4dffeebd3be..6032212b300 100644 --- a/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/VTMonitor.java +++ b/test/hotspot/jtreg/runtime/valhalla/inlinetypes/verifier/VTMonitor.java @@ -29,7 +29,7 @@ * @run main/othervm -Xverify:remote VTMonitor */ -public inline final class VTMonitor { +public primitive final class VTMonitor { final int x; final int y; diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java index 2d0013250b6..f16228cf15b 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,7 +98,7 @@ public static void main(String[] args) throws Exception { } try { - coreFileName = CoreUtils.getCoreFileLocation(crashOutput.getStdout()); + coreFileName = CoreUtils.getCoreFileLocation(crashOutput.getStdout(), crashOutput.pid()); } catch (Exception e) { cleanup(); throw e; diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java index 0a333e753d3..34906370425 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import java.util.ArrayList; import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.Platform; import jdk.test.lib.util.CoreUtils; import jtreg.SkippedException; @@ -75,12 +76,18 @@ */ public class ClhsdbFindPC { + static LingeredApp theApp = null; + static String coreFileName = null; + static ClhsdbLauncher test = null; private static void testFindPC(boolean withXcomp, boolean withCore) throws Exception { - LingeredApp theApp = null; - String coreFileName = null; try { - ClhsdbLauncher test = new ClhsdbLauncher(); + String segvAddress = null; + List cmds = null; + String cmdStr = null; + Map> expStrMap = null; + + test = new ClhsdbLauncher(); theApp = new LingeredAppWithTrivialMain(); theApp.setForceCrash(withCore); @@ -97,24 +104,38 @@ private static void testFindPC(boolean withXcomp, boolean withCore) throws Excep } System.out.println("with pid " + theApp.getPid()); - // Get the core file name if we are debugging a core instead of live process if (withCore) { - coreFileName = CoreUtils.getCoreFileLocation(theApp.getOutput().getStdout()); - } + String crashOutput = theApp.getOutput().getStdout(); + // Get the core file name if we are debugging a core instead of live process + coreFileName = CoreUtils.getCoreFileLocation(crashOutput, theApp.getPid()); + // Get the SEGV Address from the following line: + // # SIGSEGV (0xb) at pc=0x00007f20a897f7f4, pid=8561, tid=8562 + String[] parts = crashOutput.split(" pc="); + String[] tokens = parts[1].split(","); + segvAddress = tokens[0]; - // Run 'jstack -v' command to get the findpc address - List cmds = List.of("jstack -v"); - String output; - if (withCore) { - output = test.runOnCore(coreFileName, cmds, null, null); - } else { - output = test.run(theApp.getPid(), cmds, null, null); + // Test the 'findpc' command passing in the SEGV address + cmds = new ArrayList(); + cmdStr = "findpc " + segvAddress; + cmds.add(cmdStr); + expStrMap = new HashMap<>(); + if (Platform.isOSX()) { + // OSX will only find addresses in JVM libraries, not user or system libraries + expStrMap.put(cmdStr, List.of("In unknown location")); + } else { // symbol lookups not supported with OSX live process + expStrMap.put(cmdStr, List.of("Java_jdk_test_lib_apps_LingeredApp_crash")); + } + runTest(withCore, cmds, expStrMap); } + // Run 'jstack -v' command to get the pc and other useful values + cmds = List.of("jstack -v"); + String jStackOutput = runTest(withCore, cmds, null); + // Extract pc address from the following line: // - LingeredAppWithTrivialMain.main(java.lang.String[]) @bci=1, line=33, pc=0x00007ff18ff519f0, ... String pcAddress = null; - String[] parts = output.split("LingeredAppWithTrivialMain.main"); + String[] parts = jStackOutput.split("LingeredAppWithTrivialMain.main"); String[] tokens = parts[1].split(" "); for (String token : tokens) { if (token.contains("pc")) { @@ -128,11 +149,11 @@ private static void testFindPC(boolean withXcomp, boolean withCore) throws Excep throw new RuntimeException("Cannot find LingeredAppWithTrivialMain.main pc in output"); } - // Test the 'findpc' command passing in the pc obtained from above + // Test the 'findpc' command passing in the pc obtained from jstack above cmds = new ArrayList(); - String cmdStr = "findpc " + pcAddress; + cmdStr = "findpc " + pcAddress; cmds.add(cmdStr); - Map> expStrMap = new HashMap<>(); + expStrMap = new HashMap<>(); if (withXcomp) { expStrMap.put(cmdStr, List.of( "In code in NMethod for LingeredAppWithTrivialMain.main", @@ -143,12 +164,78 @@ private static void testFindPC(boolean withXcomp, boolean withCore) throws Excep expStrMap.put(cmdStr, List.of( "In interpreter codelet")); } + runTest(withCore, cmds, expStrMap); - if (withCore) { - test.runOnCore(coreFileName, cmds, expStrMap, null); + // Run findpc on a Method*. We can find one in the jstack output. For example: + // - LingeredAppWithTrivialMain.main(java.lang.String[]) @bci=1, line=33, pc=..., Method*=0x0000008041000208 ... + // This is testing the PointerFinder support for C++ MetaData types. + parts = jStackOutput.split("LingeredAppWithTrivialMain.main"); + parts = parts[1].split("Method\\*="); + parts = parts[1].split(" "); + String methodAddr = parts[0]; + cmdStr = "findpc " + methodAddr; + cmds = List.of(cmdStr); + expStrMap = new HashMap<>(); + expStrMap.put(cmdStr, List.of("Method ", + "LingeredAppWithTrivialMain.main", + methodAddr)); + runTest(withCore, cmds, expStrMap); + + // Run findpc on a JavaThread*. We can find one in the jstack output. + // The tid for a thread is it's JavaThread*. For example: + // "main" #1 prio=5 tid=0x00000080263398f0 nid=0x277e0 ... + // This is testing the PointerFinder support for all C++ types other than MetaData types. + parts = jStackOutput.split("tid="); + parts = parts[1].split(" "); + String tid = parts[0]; // address of the JavaThread + cmdStr = "findpc " + tid; + cmds = List.of(cmdStr); + expStrMap = new HashMap<>(); + expStrMap.put(cmdStr, List.of("Is of type JavaThread")); + runTest(withCore, cmds, expStrMap); + + // Run findpc on a java stack address. We can find one in the jstack output. + // "main" #1 prio=5 tid=... nid=0x277e0 waiting on condition [0x0000008025aef000] + // The stack address is the last word between the brackets. + // This is testing the PointerFinder support for thread stack addresses. + parts = jStackOutput.split("tid="); + parts = parts[1].split(" \\["); + parts = parts[1].split("\\]"); + String stackAddress = parts[0]; // address of the thread's stack + cmdStr = "findpc " + stackAddress; + cmds = List.of(cmdStr); + expStrMap = new HashMap<>(); + expStrMap.put(cmdStr, List.of("In java stack")); + runTest(withCore, cmds, expStrMap); + + // Run 'examine ' using a thread's tid as the address. The + // examine output will be the of the form: + // : + // Where is the word stored at . also happens to + // be the vtable address. We then run findpc on this vtable address. + // This tests PointerFinder support for native C++ symbols. + cmds = List.of("examine " + tid); + String examineOutput = runTest(withCore, cmds, null); + // Extract . + parts = examineOutput.split(tid + ": "); + String value = parts[1]; + // Use findpc on . The output should look something like: + // Address 0x00007fed86f610b8: vtable for JavaThread + 0x10 + cmdStr = "findpc " + value; + cmds = List.of(cmdStr); + expStrMap = new HashMap<>(); + if (Platform.isWindows()) { + expStrMap.put(cmdStr, List.of("jvm.+JavaThread")); + } else if (Platform.isOSX()) { + if (withCore) { + expStrMap.put(cmdStr, List.of("__ZTV10JavaThread")); + } else { // symbol lookups not supported with OSX live process + expStrMap.put(cmdStr, List.of("In unknown location")); + } } else { - test.run(theApp.getPid(), cmds, expStrMap, null); + expStrMap.put(cmdStr, List.of("vtable for JavaThread")); } + runTest(withCore, cmds, expStrMap); } catch (SkippedException se) { throw se; } catch (Exception ex) { @@ -160,6 +247,16 @@ private static void testFindPC(boolean withXcomp, boolean withCore) throws Excep } } + private static String runTest(boolean withCore, List cmds, Map> expStrMap) + throws Exception + { + if (withCore) { + return test.runOnCore(coreFileName, cmds, expStrMap, null); + } else { + return test.run(theApp.getPid(), cmds, expStrMap, null); + } + } + public static void main(String[] args) throws Exception { boolean withXcomp = Boolean.parseBoolean(args[0]); boolean withCore = Boolean.parseBoolean(args[1]); diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java index c92bc7ded9f..da872b8dad8 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackXcompStress.java @@ -74,7 +74,7 @@ private static void runJstackInLoop(LingeredApp app) throws Exception { System.err.println(out.getStderr()); } - out.stderrShouldBeEmptyIgnoreVMWarnings(); + out.stderrShouldBeEmptyIgnoreDeprecatedWarnings(); out.stdoutShouldNotContain("Error occurred during stack walking:"); out.stdoutShouldContain(LingeredAppWithRecComputation.THREAD_NAME); List stdoutList = Arrays.asList(out.getStdout().split("\\R")); diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java index 49388f5d526..961311f5d5b 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -144,6 +144,9 @@ private String runCmd(List commands, System.out.println("Output: "); System.out.println(output); + // -Xcheck:jni might be set via TEST_VM_OPTS. Make sure there are no warnings. + oa.shouldNotMatch("^WARNING: JNI local refs:.*$"); + oa.shouldNotMatch("^WARNING in native method:.*$"); // This will detect most SA failures, including during the attach. oa.shouldNotMatch("^sun.jvm.hotspot.debugger.DebuggerException:.*$"); // This will detect unexpected exceptions, like NPEs and asserts, that are caught diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbPmap.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbPmap.java index 54e732af76c..6f0023a21e9 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPmap.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPmap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,7 @@ public static void main(String[] args) throws Exception { if (withCore) { String crashOutput = theApp.getOutput().getStdout(); - coreFileName = CoreUtils.getCoreFileLocation(crashOutput); + coreFileName = CoreUtils.getCoreFileLocation(crashOutput, theApp.getPid()); } List cmds = List.of("pmap"); diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbPstack.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbPstack.java index 5eb162f9585..e4101a8c372 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbPstack.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbPstack.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,7 @@ public static void main(String[] args) throws Exception { if (withCore) { String crashOutput = theApp.getOutput().getStdout(); - coreFileName = CoreUtils.getCoreFileLocation(crashOutput); + coreFileName = CoreUtils.getCoreFileLocation(crashOutput, theApp.getPid()); } List cmds = List.of("pstack -v"); diff --git a/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java b/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java index d888b78b5c3..7cdc39175a4 100644 --- a/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java +++ b/test/hotspot/jtreg/serviceability/sa/JhsdbThreadInfoTest.java @@ -68,7 +68,7 @@ public static void main(String[] args) throws Exception { out.shouldNotContain(" prio=0 "); out.shouldNotContain(" java.lang.Thread.State: UNKNOWN"); - out.stderrShouldBeEmptyIgnoreVMWarnings(); + out.stderrShouldBeEmptyIgnoreDeprecatedWarnings(); System.out.println("Test Completed"); } catch (Exception ex) { diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java index a10d757266a..def56bc693f 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackLock.java @@ -65,7 +65,7 @@ public static void main (String... args) throws Exception { out.shouldMatch("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Thread\\)$"); out.shouldMatch("^\\s+- locked <0x[0-9a-f]+> \\(a java\\.lang\\.Class for int\\)$"); - out.stderrShouldBeEmptyIgnoreVMWarnings(); + out.stderrShouldBeEmptyIgnoreDeprecatedWarnings(); System.out.println("Test Completed"); } finally { diff --git a/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java b/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java index 662d55a7421..1c861f8c601 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJmapCore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,9 +77,9 @@ static void test(String type) throws Throwable { // If we are going to force a core dump, apply "ulimit -c unlimited" if we can. pb = CoreUtils.addCoreUlimitCommand(pb); - OutputAnalyzer output = ProcessTools.executeProcess(pb); + OutputAnalyzer output = ProcessTools.executeProcess(pb); - String coreFileName = CoreUtils.getCoreFileLocation(output.getStdout()); + String coreFileName = CoreUtils.getCoreFileLocation(output.getStdout(), output.pid()); File core = new File(coreFileName); File dumpFile = new File("heap.hprof"); JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb"); diff --git a/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java b/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java index f90fafe2430..a1c5e5a4af4 100644 --- a/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java +++ b/test/hotspot/jtreg/serviceability/sa/sadebugd/DebugdConnectTest.java @@ -70,7 +70,7 @@ private static void runJSTACK(String id) throws IOException, InterruptedExceptio OutputAnalyzer out = runJHSDB("jstack", id); out.shouldContain("LingeredApp"); - out.stderrShouldBeEmptyIgnoreVMWarnings(); + out.stderrShouldBeEmptyIgnoreDeprecatedWarnings(); out.shouldHaveExitValue(0); } @@ -78,7 +78,7 @@ private static void runJMAP(String id) throws IOException, InterruptedException OutputAnalyzer out = runJHSDB("jmap", id); out.shouldContain("JVM version is"); - out.stderrShouldBeEmptyIgnoreVMWarnings(); + out.stderrShouldBeEmptyIgnoreDeprecatedWarnings(); out.shouldHaveExitValue(0); } @@ -86,7 +86,7 @@ private static void runJINFO(String id) throws IOException, InterruptedException OutputAnalyzer out = runJHSDB("jinfo", id); out.shouldContain("Java System Properties:"); - out.stderrShouldBeEmptyIgnoreVMWarnings(); + out.stderrShouldBeEmptyIgnoreDeprecatedWarnings(); out.shouldHaveExitValue(0); } @@ -94,7 +94,7 @@ private static void runJSNAP(String id) throws IOException, InterruptedException OutputAnalyzer out = runJHSDB("jsnap", id); out.shouldContain("java.vm.name="); - out.stderrShouldBeEmptyIgnoreVMWarnings(); + out.stderrShouldBeEmptyIgnoreDeprecatedWarnings(); out.shouldHaveExitValue(0); } diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/JumbleGC/Tree.java b/test/hotspot/jtreg/vmTestbase/gc/gctests/JumbleGC/Tree.java index 1025ea588fb..ea3d045fcff 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/JumbleGC/Tree.java +++ b/test/hotspot/jtreg/vmTestbase/gc/gctests/JumbleGC/Tree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,7 +74,7 @@ synchronized void addElement(int o) { else q.right = newnode; elementCount++; - TreeValues.addElement(new Integer(o)); + TreeValues.addElement(Integer.valueOf(o)); } diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/PhantomHelper.java b/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/PhantomHelper.java index 050e0404707..c849b496ccd 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/PhantomHelper.java +++ b/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/PhantomHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,7 +101,7 @@ public static final String checkAllHashCodes(ReferenceQueue rq, PRHelper prh = (PRHelper) rq.remove(1000); if (prh != null) { - Integer ik = new Integer(prh.getReferentHashCode()); + Integer ik = Integer.valueOf(prh.getReferentHashCode()); PhantomHelper ph = (PhantomHelper) hmHelper.get(ik); if (ph != null) { @@ -110,7 +110,7 @@ public static final String checkAllHashCodes(ReferenceQueue rq, ph.decreaseHashCounter(); if (ph.getHashCounter() == 0) { hmHelper.remove( - new Integer(prh.getReferentHashCode())); + Integer.valueOf(prh.getReferentHashCode())); } else { hmHelper.put(ik, ph); } diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/PhantomReferenceEvilTest/PhantomReferenceEvilTest.java b/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/PhantomReferenceEvilTest/PhantomReferenceEvilTest.java index a037f81301b..6ce98d5b8ed 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/PhantomReferenceEvilTest/PhantomReferenceEvilTest.java +++ b/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/PhantomReferenceEvilTest/PhantomReferenceEvilTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -111,7 +111,7 @@ public final void run() { byte[] tmp = new byte[allocationSize]; if (counter % keepEveryXthObject == 0) { - Integer ik = new Integer(tmp.hashCode()); + Integer ik = Integer.valueOf(tmp.hashCode()); if (hmHelper.containsKey(ik)) { PhantomHelper ph = (PhantomHelper) hmHelper.get(ik); ph.increaseHashCounter(); diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/PhantomReferenceTest/PhantomReferenceTest.java b/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/PhantomReferenceTest/PhantomReferenceTest.java index 270fa5306b7..c76bc226338 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/PhantomReferenceTest/PhantomReferenceTest.java +++ b/test/hotspot/jtreg/vmTestbase/gc/gctests/PhantomReference/PhantomReferenceTest/PhantomReferenceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,7 +91,7 @@ public final void run() { int allocationSize = ((int) (rndGenerator.nextDouble() * multiplier)) + minSize; byte[] tmp = new byte[allocationSize]; - Integer ik = new Integer(tmp.hashCode()); + Integer ik = Integer.valueOf(tmp.hashCode()); if (hmHelper.containsKey(ik)) { PhantomHelper ph = (PhantomHelper) hmHelper.get(ik); ph.increaseHashCounter(); diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/ReferencesGC/ReferencesGC.java b/test/hotspot/jtreg/vmTestbase/gc/gctests/ReferencesGC/ReferencesGC.java index 9857b037ee3..0c75473bd22 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/ReferencesGC/ReferencesGC.java +++ b/test/hotspot/jtreg/vmTestbase/gc/gctests/ReferencesGC/ReferencesGC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,9 +64,9 @@ public static void main(String[] args) { public static void parseArgs(String[] args) { for (int i = 0; i < args.length; i++) { if (args[i].compareTo("-range") == 0) { - RANGE = new Integer(args[++i]).intValue(); + RANGE = Integer.valueOf(args[++i]).intValue(); } else if (args[i].compareTo("-ratio") == 0) { - RATIO = new Float(args[++i]).floatValue(); + RATIO = Float.valueOf(args[++i]).floatValue(); } } REMOVE = (int) (RANGE * RATIO); diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReferenceGC/WeakReferenceGC.java b/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReferenceGC/WeakReferenceGC.java index f351a8d40ea..205897d9099 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReferenceGC/WeakReferenceGC.java +++ b/test/hotspot/jtreg/vmTestbase/gc/gctests/WeakReferenceGC/WeakReferenceGC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -170,13 +170,13 @@ private boolean hasPassed() { private void parseTestParams(String args[]) { for (int i = 0; i < args.length; i++) { if (args[i].compareTo("-numList") == 0) { - numLists = new Integer(args[++i]).intValue(); + numLists = Integer.valueOf(args[++i]).intValue(); } else if (args[i].compareTo("-qFactor") == 0) { - qFactor = new Float(args[++i]).floatValue(); + qFactor = Float.valueOf(args[++i]).floatValue(); } else if (args[i].compareTo("-gcCount") == 0) { - gcCount = new Integer(args[++i]).intValue(); + gcCount = Integer.valueOf(args[++i]).intValue(); } else if (args[i].compareTo("-iter") == 0) { - loopCount = new Integer(args[++i]).intValue(); + loopCount = Integer.valueOf(args[++i]).intValue(); // } else { // System.err.println("usage : " + // "java WeakReferenceGC [-numList ] " + diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest01/gctest01.java b/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest01/gctest01.java index 2e041dbaa1a..787c563837b 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest01/gctest01.java +++ b/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest01/gctest01.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -195,7 +195,7 @@ public void run() { if (args.length > 0) { try { - peopleLimit = new Integer(args[0]).intValue(); + peopleLimit = Integer.valueOf(args[0]).intValue(); } catch (NumberFormatException e) { log.info(usage); throw new TestBug("Bad input to gctest01." + @@ -205,7 +205,7 @@ public void run() { if (args.length > 1 ) { try { - LOOPCOUNT = new Integer(args[1]).intValue(); + LOOPCOUNT = Integer.valueOf(args[1]).intValue(); } catch (NumberFormatException e) { log.error(usage); throw new TestBug("Bad input to gctest01." + diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest02/gctest02.java b/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest02/gctest02.java index 29175d78d93..74011a1a40a 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest02/gctest02.java +++ b/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest02/gctest02.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -180,7 +180,7 @@ public static void main(String args[] ) { { try { - peopleLimit = new Integer(args[0]).intValue(); + peopleLimit = Integer.valueOf(args[0]).intValue(); } catch (NumberFormatException e) { diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest03/gctest03.java b/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest03/gctest03.java index 412f00e4714..33ea2fbda89 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest03/gctest03.java +++ b/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest03/gctest03.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,7 +71,7 @@ public void run() { if (args.length > 0) { try { - dataNodeLimit = new Integer(args[0]).intValue(); + dataNodeLimit = Integer.valueOf(args[0]).intValue(); } catch (NumberFormatException e) { throw new TestBug("Bad input to gctest03. Expected integer, " + " got: ->" + args[0] + "<-", e); diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest04/gctest04.java b/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest04/gctest04.java index 37ac8674337..440b98aa834 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest04/gctest04.java +++ b/test/hotspot/jtreg/vmTestbase/gc/gctests/gctest04/gctest04.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ public static void main(String args[] ) { try { - queueLimit = new Integer(args[0]).intValue(); + queueLimit = Integer.valueOf(args[0]).intValue(); } catch (NumberFormatException e) { diff --git a/test/hotspot/jtreg/vmTestbase/gc/hashcode/ExternalHashingTest/ExternalHashingTest.java b/test/hotspot/jtreg/vmTestbase/gc/hashcode/ExternalHashingTest/ExternalHashingTest.java index 4bc77b1611a..21d3c7b4925 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/hashcode/ExternalHashingTest/ExternalHashingTest.java +++ b/test/hotspot/jtreg/vmTestbase/gc/hashcode/ExternalHashingTest/ExternalHashingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -239,7 +239,7 @@ private static void mungeObjects() { for (int i = 0; i < BATCH_SIZE; i++) { /* Add all of the results of this pass to the global list. */ allObjects.add(hashedList[i]); - allHashes.add(new Integer(foundHashes[i])); + allHashes.add(Integer.valueOf(foundHashes[i])); /* Create even more garbage for the GC to find */ garbageMonger[i] = new Object(); diff --git a/test/hotspot/jtreg/vmTestbase/jit/FloatingPoint/FPCompare/TestFPBinop/TestFPBinop.java b/test/hotspot/jtreg/vmTestbase/jit/FloatingPoint/FPCompare/TestFPBinop/TestFPBinop.java index 9a361dd9279..3518d3cc752 100644 --- a/test/hotspot/jtreg/vmTestbase/jit/FloatingPoint/FPCompare/TestFPBinop/TestFPBinop.java +++ b/test/hotspot/jtreg/vmTestbase/jit/FloatingPoint/FPCompare/TestFPBinop/TestFPBinop.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,10 +68,10 @@ public class TestFPBinop { * from simplifying some of the expressions by using algebraic * identities. */ static { - fOne = new Integer(1).floatValue(); - fZero = new Integer(0).floatValue(); - dOne = new Integer(1).doubleValue(); - dZero = new Integer(0).doubleValue(); + fOne = Integer.valueOf(1).floatValue(); + fZero = Integer.valueOf(0).floatValue(); + dOne = Integer.valueOf(1).doubleValue(); + dZero = Integer.valueOf(0).doubleValue(); } static final boolean DEBUG = false; @@ -368,7 +368,7 @@ static double i(double x) { static int index(float x) { for (int i = 0; i < floatValues.length; i++) { - if (new Float(x).equals(new Float(floatValues[i]))) + if (Float.valueOf(x).equals(Float.valueOf(floatValues[i]))) return i; } throw new TestFailure("ERROR: can't find " + x + " in floatValues."); @@ -376,7 +376,7 @@ static int index(float x) { static int index(double x) { for (int i = 0; i < doubleValues.length; i++) { - if (new Double(x).equals(new Double(doubleValues[i]))) + if (Double.valueOf(x).equals(Double.valueOf(doubleValues[i]))) return i; } throw new TestFailure("ERROR: can't find " + x + " in doubleValues."); diff --git a/test/hotspot/jtreg/vmTestbase/jit/graph/test1.java b/test/hotspot/jtreg/vmTestbase/jit/graph/test1.java index 8b6a5f7a7d1..3d635551915 100644 --- a/test/hotspot/jtreg/vmTestbase/jit/graph/test1.java +++ b/test/hotspot/jtreg/vmTestbase/jit/graph/test1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,10 +53,10 @@ public void callMe(Vector summation, Vector ID, Long functionDepth, Integer stat if (staticFunctionDepth.intValue() > 0) { numFcalls = functionDepth; - staticFcalls = new Integer(staticFunctionDepth.intValue() - 1); + staticFcalls = Integer.valueOf(staticFunctionDepth.intValue() - 1); methodCallStr = Globals.returnNextStaticMethod(classID); } else { - numFcalls = new Long(functionDepth.longValue() - 1); + numFcalls = Long.valueOf(functionDepth.longValue() - 1); staticFcalls = staticFunctionDepth; methodCallStr = Globals.nextRandomMethod(); } diff --git a/test/hotspot/jtreg/vmTestbase/jit/graph/test2.java b/test/hotspot/jtreg/vmTestbase/jit/graph/test2.java index ba21495d546..592edf42de2 100644 --- a/test/hotspot/jtreg/vmTestbase/jit/graph/test2.java +++ b/test/hotspot/jtreg/vmTestbase/jit/graph/test2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,12 +52,12 @@ public void CallCallMe(Vector summation, Vector ID, Long functionDepth, Integer Integer staticFcalls; if (staticFunctionDepth.intValue() > 0) { numFcalls = functionDepth; - staticFcalls = new Integer(staticFunctionDepth.intValue() - 1); + staticFcalls = Integer.valueOf(staticFunctionDepth.intValue() - 1); methodCallStr = Globals.returnNextStaticMethod(MethodID[1]); Globals.addFunctionIDToVector(methodCallStr.id, ID); } else { - numFcalls = new Long(functionDepth.longValue() - 1); + numFcalls = Long.valueOf(functionDepth.longValue() - 1); staticFcalls = staticFunctionDepth; Globals.addFunctionIDToVector(MethodID[0], ID); callMe(summation, ID, numFcalls, staticFcalls); @@ -94,11 +94,11 @@ public void callMe(Vector summation, Vector ID, Long functionDepth, Integer stat Integer staticFcalls; if (staticFunctionDepth.intValue() > 0) { numFcalls = functionDepth; - staticFcalls = new Integer(staticFunctionDepth.intValue() - 1); + staticFcalls = Integer.valueOf(staticFunctionDepth.intValue() - 1); methodCallStr = Globals.returnNextStaticMethod(MethodID[0]); } else { - numFcalls = new Long(functionDepth.longValue() - 1); + numFcalls = Long.valueOf(functionDepth.longValue() - 1); staticFcalls = staticFunctionDepth; methodCallStr = Globals.nextRandomMethod(); } diff --git a/test/hotspot/jtreg/vmTestbase/jit/graph/test3.java b/test/hotspot/jtreg/vmTestbase/jit/graph/test3.java index 73e852dcf6b..339d5812211 100644 --- a/test/hotspot/jtreg/vmTestbase/jit/graph/test3.java +++ b/test/hotspot/jtreg/vmTestbase/jit/graph/test3.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,17 +59,17 @@ public void selfRecursion(Vector summation, Vector ID, Long functionDepth, Integ // make a static call if (staticFunctionDepth.intValue() > 0) { numFcalls = functionDepth; - staticFcalls = new Integer(staticFunctionDepth.intValue() - 1); + staticFcalls = Integer.valueOf(staticFunctionDepth.intValue() - 1); methodCallStr = Globals.returnNextStaticMethod(MethodID[1]); } else if (localNumLoops > 0) { // make a recursive call - numFcalls = new Long(functionDepth.longValue() - 1); + numFcalls = Long.valueOf(functionDepth.longValue() - 1); staticFcalls = staticFunctionDepth; Globals.addFunctionIDToVector(MethodID[1], ID); localNumLoops--; selfRecursion(summation, ID, numFcalls, staticFcalls); return; } else { // make a random call - numFcalls = new Long(functionDepth.longValue() - 1); + numFcalls = Long.valueOf(functionDepth.longValue() - 1); staticFcalls = staticFunctionDepth; methodCallStr = Globals.nextRandomMethod(); @@ -101,10 +101,10 @@ public void callMe(Vector summation, Vector ID, Long functionDepth, Integer stat Integer staticFcalls; if (staticFunctionDepth.intValue() > 0) { numFcalls = functionDepth; - staticFcalls = new Integer(staticFunctionDepth.intValue() - 1); + staticFcalls = Integer.valueOf(staticFunctionDepth.intValue() - 1); methodCallStr = Globals.returnNextStaticMethod(MethodID[0]); } else { - numFcalls = new Long(functionDepth.longValue() - 1); + numFcalls = Long.valueOf(functionDepth.longValue() - 1); staticFcalls = staticFunctionDepth; methodCallStr = Globals.nextRandomMethod(); } diff --git a/test/hotspot/jtreg/vmTestbase/jit/graph/test4.java b/test/hotspot/jtreg/vmTestbase/jit/graph/test4.java index 42346c463be..9f403ba5e64 100644 --- a/test/hotspot/jtreg/vmTestbase/jit/graph/test4.java +++ b/test/hotspot/jtreg/vmTestbase/jit/graph/test4.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,12 +51,12 @@ public void CallCallMe(Vector summation, Vector ID, Long functionDepth, Integer Integer staticFcalls; if (staticFunctionDepth.intValue() > 0) { numFcalls = functionDepth; - staticFcalls = new Integer(staticFunctionDepth.intValue() - 1); + staticFcalls = Integer.valueOf(staticFunctionDepth.intValue() - 1); methodCallStr = Globals.returnNextStaticMethod(MethodID[1]); Globals.addFunctionIDToVector(methodCallStr.id, ID); } else { - numFcalls = new Long(functionDepth.longValue() - 1); + numFcalls = Long.valueOf(functionDepth.longValue() - 1); staticFcalls = staticFunctionDepth; Globals.addFunctionIDToVector(MethodID[0], ID); super.callMe(summation, ID, numFcalls, staticFcalls); @@ -89,11 +89,11 @@ public void callMe(Vector summation, Vector ID, Long functionDepth, Integer stat Integer staticFcalls; if (staticFunctionDepth.intValue() > 0) { numFcalls = functionDepth; - staticFcalls = new Integer(staticFunctionDepth.intValue() - 1); + staticFcalls = Integer.valueOf(staticFunctionDepth.intValue() - 1); methodCallStr = Globals.returnNextStaticMethod(MethodID[2]); } else { long temp = functionDepth.longValue() - 2; - numFcalls = new Long(temp / 2); + numFcalls = Long.valueOf(temp / 2); staticFcalls = staticFunctionDepth; if (Globals.VERBOSE) { @@ -117,7 +117,7 @@ public void callMe(Vector summation, Vector ID, Long functionDepth, Integer stat if (Globals.VERBOSE) { System.out.println(" test4.callMe - Starting Branch 2"); } - numFcalls = new Long(temp); + numFcalls = Long.valueOf(temp); methodCallStr = Globals.nextRandomMethod(); } Globals.addFunctionIDToVector(methodCallStr.id, ID); diff --git a/test/hotspot/jtreg/vmTestbase/jit/graph/test5.java b/test/hotspot/jtreg/vmTestbase/jit/graph/test5.java index f59046f62da..14fbd8fedf5 100644 --- a/test/hotspot/jtreg/vmTestbase/jit/graph/test5.java +++ b/test/hotspot/jtreg/vmTestbase/jit/graph/test5.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -164,10 +164,10 @@ public void factTest(Vector summation, Vector ID, Long functionDepth, Integer st if (staticFunctionDepth.intValue() > 0) { numFcalls = functionDepth; - staticFcalls = new Integer(staticFunctionDepth.intValue() - 1); + staticFcalls = Integer.valueOf(staticFunctionDepth.intValue() - 1); methodCallStr = Globals.returnNextStaticMethod(MethodID[0]); } else { - numFcalls = new Long(functionDepth.longValue() - 1); + numFcalls = Long.valueOf(functionDepth.longValue() - 1); staticFcalls = staticFunctionDepth; methodCallStr = Globals.nextRandomMethod(); } @@ -205,10 +205,10 @@ public void fiboTest(Vector summation, Vector ID, Long functionDepth, Integer st Integer staticFcalls; if (staticFunctionDepth.intValue() > 0) { numFcalls = functionDepth; - staticFcalls = new Integer(staticFunctionDepth.intValue() - 1); + staticFcalls = Integer.valueOf(staticFunctionDepth.intValue() - 1); methodCallStr = Globals.returnNextStaticMethod(MethodID[1]); } else { - numFcalls = new Long(functionDepth.longValue() - 1); + numFcalls = Long.valueOf(functionDepth.longValue() - 1); staticFcalls = staticFunctionDepth; methodCallStr = Globals.nextRandomMethod(); } @@ -246,10 +246,10 @@ public void combTest(Vector summation, Vector ID, Long functionDepth, Integer st Integer staticFcalls; if (staticFunctionDepth.intValue() > 0) { numFcalls = functionDepth; - staticFcalls = new Integer(staticFunctionDepth.intValue() - 1); + staticFcalls = Integer.valueOf(staticFunctionDepth.intValue() - 1); methodCallStr = Globals.returnNextStaticMethod(MethodID[2]); } else { - numFcalls = new Long(functionDepth.longValue() - 1); + numFcalls = Long.valueOf(functionDepth.longValue() - 1); staticFcalls = staticFunctionDepth; methodCallStr = Globals.nextRandomMethod(); } @@ -291,10 +291,10 @@ public void pascalTest(Vector summation, Vector ID, Long functionDepth, Integer Integer staticFcalls; if (staticFunctionDepth.intValue() > 0) { numFcalls = functionDepth; - staticFcalls = new Integer(staticFunctionDepth.intValue() - 1); + staticFcalls = Integer.valueOf(staticFunctionDepth.intValue() - 1); methodCallStr = Globals.returnNextStaticMethod(MethodID[3]); } else { - numFcalls = new Long(functionDepth.longValue() - 1); + numFcalls = Long.valueOf(functionDepth.longValue() - 1); staticFcalls = staticFunctionDepth; methodCallStr = Globals.nextRandomMethod(); } diff --git a/test/hotspot/jtreg/vmTestbase/jit/graph/test6.java b/test/hotspot/jtreg/vmTestbase/jit/graph/test6.java index 892b33d1b18..f2d649d7457 100644 --- a/test/hotspot/jtreg/vmTestbase/jit/graph/test6.java +++ b/test/hotspot/jtreg/vmTestbase/jit/graph/test6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,10 +65,10 @@ public synchronized void rbTest(Vector summation, Vector ID, Long functionDepth, if (staticFunctionDepth.intValue() > 0) { numFcalls = functionDepth; - staticFcalls = new Integer(staticFunctionDepth.intValue() - 1); + staticFcalls = Integer.valueOf(staticFunctionDepth.intValue() - 1); methodCallStr = Globals.returnNextStaticMethod(MethodID[0]); } else { - numFcalls = new Long(functionDepth.longValue() - 1); + numFcalls = Long.valueOf(functionDepth.longValue() - 1); staticFcalls = staticFunctionDepth; methodCallStr = Globals.nextRandomMethod(); } @@ -82,11 +82,11 @@ public synchronized void rbTest(Vector summation, Vector ID, Long functionDepth, // code guarantees no duplicates for (int i = 0; i < numElements; i++) { int nextKey = localNumGen.nextInt(16385); - while (temp.indexOf(new Integer(nextKey)) != -1) { + while (temp.indexOf(Integer.valueOf(nextKey)) != -1) { nextKey = localNumGen.nextInt(16385); } - temp.addElement(new Integer(nextKey)); + temp.addElement(Integer.valueOf(nextKey)); dataArray[i] = nextKey; insertArray[i] = false; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop_exception/pop_exception001/pop_exception001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop_exception/pop_exception001/pop_exception001a.java index 354df01f3cb..462a2d2225b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop_exception/pop_exception001/pop_exception001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/pop_exception/pop_exception001/pop_exception001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ private Object getItem(int i) { if (i == 5) { throw new NullPointerException("Something went wrong"); } else { - return new Integer(i); + return Integer.valueOf(i); } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch001/unwatch001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch001/unwatch001a.java index 67b025ac48e..63420b0d9a6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch001/unwatch001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch001/unwatch001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,7 @@ void updateFields(boolean flag) { fS1 = flag ? fS1 : new boolean[] {fS0}; fS2 = flag ? fS2 : new boolean[][] {fS1}; - FS0 = flag ? FS0 : new Boolean(false); + FS0 = flag ? FS0 : Boolean.valueOf(false); FS1 = flag ? FS1 : new Boolean[] {FS0}; FS2 = flag ? FS2 : new Boolean[][] {FS1}; @@ -102,11 +102,11 @@ void updateFields(boolean flag) { fT0 = flag ? fT0 : Float.MIN_VALUE; fV0 = flag ? fV0 : Integer.MIN_VALUE; - FP0 = flag ? FP0 : new Byte(Byte.MIN_VALUE) ; - FU0 = flag ? FU0 : new Character(Character.MIN_VALUE); - FR0 = flag ? FR0 : new Double(Double.MIN_VALUE); - FT0 = flag ? FT0 : new Float(Float.MIN_VALUE); - FV0 = flag ? FV0 : new Long(Long.MIN_VALUE); + FP0 = flag ? FP0 : Byte.valueOf(Byte.MIN_VALUE) ; + FU0 = flag ? FU0 : Character.valueOf(Character.MIN_VALUE); + FR0 = flag ? FR0 : Double.valueOf(Double.MIN_VALUE); + FT0 = flag ? FT0 : Float.valueOf(Float.MIN_VALUE); + FV0 = flag ? FV0 : Long.valueOf(Long.MIN_VALUE); fP1 = flag ? fP1 : new byte[] {fP0}; fP2 = flag ? fP2 : new byte[][] {fP1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch002/unwatch002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch002/unwatch002a.java index 309af7e77b7..5e34df9ba01 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch002/unwatch002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/unwatch/unwatch002/unwatch002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,7 @@ void updateFields(boolean flag) { fS1 = flag ? fS1 : new boolean[] {fS0}; fS2 = flag ? fS2 : new boolean[][] {fS1}; - FS0 = flag ? FS0 : new Boolean(false); + FS0 = flag ? FS0 : Boolean.valueOf(false); FS1 = flag ? FS1 : new Boolean[] {FS0}; FS2 = flag ? FS2 : new Boolean[][] {FS1}; @@ -102,11 +102,11 @@ void updateFields(boolean flag) { fT0 = flag ? fT0 : Float.MIN_VALUE; fV0 = flag ? fV0 : Integer.MIN_VALUE; - FP0 = flag ? FP0 : new Byte(Byte.MIN_VALUE) ; - FU0 = flag ? FU0 : new Character(Character.MIN_VALUE); - FR0 = flag ? FR0 : new Double(Double.MIN_VALUE); - FT0 = flag ? FT0 : new Float(Float.MIN_VALUE); - FV0 = flag ? FV0 : new Long(Long.MIN_VALUE); + FP0 = flag ? FP0 : Byte.valueOf(Byte.MIN_VALUE) ; + FU0 = flag ? FU0 : Character.valueOf(Character.MIN_VALUE); + FR0 = flag ? FR0 : Double.valueOf(Double.MIN_VALUE); + FT0 = flag ? FT0 : Float.valueOf(Float.MIN_VALUE); + FV0 = flag ? FV0 : Long.valueOf(Long.MIN_VALUE); fP1 = flag ? fP1 : new byte[] {fP0}; fP2 = flag ? fP2 : new byte[][] {fP1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch001/watch001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch001/watch001a.java index 05b378481a0..98060d1873b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch001/watch001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch001/watch001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,7 @@ void updateFields(boolean flag) { fS1 = flag ? fS1 : new boolean[] {fS0}; fS2 = flag ? fS2 : new boolean[][] {fS1}; - FS0 = flag ? FS0 : new Boolean(false); + FS0 = flag ? FS0 : Boolean.valueOf(false); FS1 = flag ? FS1 : new Boolean[] {FS0}; FS2 = flag ? FS2 : new Boolean[][] {FS1}; @@ -98,11 +98,11 @@ void updateFields(boolean flag) { fT0 = flag ? fT0 : Float.MIN_VALUE; fV0 = flag ? fV0 : Integer.MIN_VALUE; - FP0 = flag ? FP0 : new Byte(Byte.MIN_VALUE) ; - FU0 = flag ? FU0 : new Character(Character.MIN_VALUE); - FR0 = flag ? FR0 : new Double(Double.MIN_VALUE); - FT0 = flag ? FT0 : new Float(Float.MIN_VALUE); - FV0 = flag ? FV0 : new Long(Long.MIN_VALUE); + FP0 = flag ? FP0 : Byte.valueOf(Byte.MIN_VALUE) ; + FU0 = flag ? FU0 : Character.valueOf(Character.MIN_VALUE); + FR0 = flag ? FR0 : Double.valueOf(Double.MIN_VALUE); + FT0 = flag ? FT0 : Float.valueOf(Float.MIN_VALUE); + FV0 = flag ? FV0 : Long.valueOf(Long.MIN_VALUE); fP1 = flag ? fP1 : new byte[] {fP0}; fP2 = flag ? fP2 : new byte[][] {fP1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch002/watch002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch002/watch002a.java index 155a5a0b7b6..9cf77a74323 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch002/watch002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdb/watch/watch002/watch002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,7 @@ void updateFields(boolean flag) { fS1 = flag ? fS1 : new boolean[] {fS0}; fS2 = flag ? fS2 : new boolean[][] {fS1}; - FS0 = flag ? FS0 : new Boolean(false); + FS0 = flag ? FS0 : Boolean.valueOf(false); FS1 = flag ? FS1 : new Boolean[] {FS0}; FS2 = flag ? FS2 : new Boolean[][] {FS1}; @@ -98,11 +98,11 @@ void updateFields(boolean flag) { fT0 = flag ? fT0 : Float.MIN_VALUE; fV0 = flag ? fV0 : Integer.MIN_VALUE; - FP0 = flag ? FP0 : new Byte(Byte.MIN_VALUE) ; - FU0 = flag ? FU0 : new Character(Character.MIN_VALUE); - FR0 = flag ? FR0 : new Double(Double.MIN_VALUE); - FT0 = flag ? FT0 : new Float(Float.MIN_VALUE); - FV0 = flag ? FV0 : new Long(Long.MIN_VALUE); + FP0 = flag ? FP0 : Byte.valueOf(Byte.MIN_VALUE) ; + FU0 = flag ? FU0 : Character.valueOf(Character.MIN_VALUE); + FR0 = flag ? FR0 : Double.valueOf(Double.MIN_VALUE); + FT0 = flag ? FT0 : Float.valueOf(Float.MIN_VALUE); + FV0 = flag ? FV0 : Long.valueOf(Long.MIN_VALUE); fP1 = flag ? fP1 : new byte[] {fP0}; fP2 = flag ? fP2 : new byte[][] {fP1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp001a.java index e8eea9f20c2..14e12c908bb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPackagePrivate/accipp001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,16 +41,16 @@ public class accipp001a { long l0, l1[]={l0}, l2[][]={l1}, l3[][][]={l2}, l4[][][][]={l3}; short s0, s1[]={s0}, s2[][]={s1}, s3[][][]={s2}, s4[][][][]={s3}; - Boolean Z0 = new Boolean(true), Z1[] ={Z0}, Z2[][]={Z1}, Z3[][][]={Z2}, Z4[][][][]={Z3}; - Byte B0 = new Byte("0"), B1[] ={B0}, B2[][]={B1}, B3[][][]={B2}, B4[][][][]={B3}; - Character C0 = new Character('0'), C1[] ={C0}, C2[][]={C1}, C3[][][]={C2}, C4[][][][]={C3}; - Double D0 = new Double(0), D1[] ={D0}, D2[][]={D1}, D3[][][]={D2}, D4[][][][]={D3}; - Float F0 = new Float(0), F1[] ={F0}, F2[][]={F1}, F3[][][]={F2}, F4[][][][]={F3}; - Integer I0 = new Integer(0), I1[] ={I0}, I2[][]={I1}, I3[][][]={I2}, I4[][][][]={I3}; - Long L0 = new Long(0), L1[] ={L0}, L2[][]={L1}, L3[][][]={L2}, L4[][][][]={L3}; - Short Sh0 = new Short("1"), Sh1[]={Sh0}, Sh2[][]={Sh1}, Sh3[][][]={Sh2}, Sh4[][][][]={Sh3}; - String S0 = new String(" "), S1[] ={S0}, S2[][]={S1}, S3[][][]={S2}, S4[][][][]={S3}; - Object O0 = new Object(), O1[] ={O0}, O2[][]={O1}, O3[][][]={O2}, O4[][][][]={O3}; + Boolean Z0 = Boolean.valueOf(true), Z1[] ={Z0}, Z2[][]={Z1}, Z3[][][]={Z2}, Z4[][][][]={Z3}; + Byte B0 = Byte.valueOf("0"), B1[] ={B0}, B2[][]={B1}, B3[][][]={B2}, B4[][][][]={B3}; + Character C0 = Character.valueOf('0'), C1[] ={C0}, C2[][]={C1}, C3[][][]={C2}, C4[][][][]={C3}; + Double D0 = Double.valueOf(0), D1[] ={D0}, D2[][]={D1}, D3[][][]={D2}, D4[][][][]={D3}; + Float F0 = Float.valueOf(0), F1[] ={F0}, F2[][]={F1}, F3[][][]={F2}, F4[][][][]={F3}; + Integer I0 = Integer.valueOf(0), I1[] ={I0}, I2[][]={I1}, I3[][][]={I2}, I4[][][][]={I3}; + Long L0 = Long.valueOf(0), L1[] ={L0}, L2[][]={L1}, L3[][][]={L2}, L4[][][][]={L3}; + Short Sh0 = Short.valueOf("1"), Sh1[]={Sh0}, Sh2[][]={Sh1}, Sh3[][][]={Sh2}, Sh4[][][][]={Sh3}; + String S0 = new String(" "), S1[] ={S0}, S2[][]={S1}, S3[][][]={S2}, S4[][][][]={S3}; + Object O0 = new Object(), O1[] ={O0}, O2[][]={O1}, O3[][][]={O2}, O4[][][][]={O3}; private static class U {} // private ==> package private protected static class V {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001a.java index 294937f7d58..163b687a982 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPrivate/isPrivate001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,15 +46,15 @@ public class isPrivate001a { // Classes must be loaded and linked, so all fields must be // initialized - Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; - Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; - Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; - Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; - Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; - Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; - Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; - String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; - Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + Boolean Z0 = Boolean.valueOf(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = Byte.valueOf((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = Character.valueOf('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = Double.valueOf(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = Float.valueOf(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = Integer.valueOf(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = Long.valueOf(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; private static class U {} protected static class V {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001a.java index 9d66c7c6f76..361456d2ed5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isProtected/isProtected001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,15 +46,15 @@ public class isProtected001a { // Classes must be loaded and linked, so all fields must be // initialized - Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; - Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; - Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; - Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; - Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; - Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; - Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; - String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; - Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + Boolean Z0 = Boolean.valueOf(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = Byte.valueOf((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = Character.valueOf('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = Double.valueOf(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = Float.valueOf(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = Integer.valueOf(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = Long.valueOf(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; private static class U {} protected static class V {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001a.java index 916795c29e8..65493885ae0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/isPublic/isPublic001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,15 +46,15 @@ public class isPublic001a { // Classes must be loaded and linked, so all fields must be // initialized - Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; - Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; - Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; - Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; - Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; - Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; - Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; - String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; - Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + Boolean Z0 = Boolean.valueOf(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = Byte.valueOf((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = Character.valueOf('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = Double.valueOf(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = Float.valueOf(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = Integer.valueOf(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = Long.valueOf(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; private static class U {} protected static class V {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001a.java index f9583200353..19d2081780e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Accessible/modifiers/modifiers001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,13 +38,13 @@ public class modifiers001a { // Classes must be loaded and linked, so all fields must be // initialized - Boolean Z0 = new Boolean(false); - Byte B0 = new Byte((byte)1); - Character C0 = new Character('c'); - Double D0 = new Double(1); - Float F0 = new Float(1); - Integer I0 = new Integer(1); - Long L0 = new Long(1); + Boolean Z0 = Boolean.valueOf(false); + Byte B0 = Byte.valueOf((byte)1); + Character C0 = Character.valueOf('c'); + Double D0 = Double.valueOf(1); + Float F0 = Float.valueOf(1); + Integer I0 = Integer.valueOf(1); + Long L0 = Long.valueOf(1); String S0 = new String("s"); Object O0 = new Object(); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001.java index 3c4c6da441c..1736c5ec210 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -343,11 +343,11 @@ public static int run(String argv[], PrintStream out) { testFailed = true; continue; } - element = new Double(doubleValue.value()); + element = Double.valueOf(doubleValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); - if (!element.equals(new Double(DOUB[j]))) { + if (!element.equals(Double.valueOf(DOUB[j]))) { log.complain("debuger FAILURE D3> " + j + " element of " + "array " + name + " was expected " + DOUB[j] + ", but returned " + element); @@ -388,11 +388,11 @@ public static int run(String argv[], PrintStream out) { testFailed = true; continue; } - element = new Float(floatValue.value()); + element = Float.valueOf(floatValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); - if (!element.equals(new Float(FLOAT[j]))) { + if (!element.equals(Float.valueOf(FLOAT[j]))) { log.complain("debuger FAILURE F3> " + j + " element of " + "array " + name + " was expected " + FLOAT[j] + ", but returned " + element); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002.java index f74d25ceae2..7eddcfe435d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValue/getvalue002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -104,7 +104,7 @@ public static int run(String argv[], PrintStream out) { for (int i = 0; i < FIELD_NAME.length; i++) { Field field; String name = FIELD_NAME[i][0]; - Integer totalElements = new Integer(FIELD_NAME[i][1]); + Integer totalElements = Integer.valueOf(FIELD_NAME[i][1]); int lastElementIndex = totalElements.intValue() - 1; Value value; ArrayReference arrayRef; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001.java index 0d721b15599..2bf5f8ea319 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues/getvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -297,12 +297,12 @@ public static int run(String argv[], PrintStream out) { testFailed = true; continue; } - element = new Double(doubleValue.value()); + element = Double.valueOf(doubleValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); // Check element's value - if (!element.equals(new Double(DOUB[j]))) { + if (!element.equals(Double.valueOf(DOUB[j]))) { log.complain("debuger FAILURE D2> " + j + " element " + "of array " + name + " was expected " + DOUB[j] + ", but returned " + element); @@ -325,12 +325,12 @@ public static int run(String argv[], PrintStream out) { testFailed = true; continue; } - element = new Float(floatValue.value()); + element = Float.valueOf(floatValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); // Check element's value - if (!element.equals(new Float(FLOAT[j]))) { + if (!element.equals(Float.valueOf(FLOAT[j]))) { log.complain("debuger FAILURE F2> " + j + " element " + "of array " + name + " was expected " + FLOAT[j] + ", but returned " + element); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001.java index b7052f73007..154d5176d2f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -316,8 +316,8 @@ public static int run(String argv[], PrintStream out) { // Check element's value if (element != CHAR[j + i]) { - Character c = new Character('c'); - Integer n = new Integer(0); + Character c = Character.valueOf('c'); + Integer n = Integer.valueOf(0); String sReal = n.toHexString( c.getNumericValue(CHAR[j + i]) ); @@ -347,12 +347,12 @@ public static int run(String argv[], PrintStream out) { testFailed = true; continue; } - element = new Double(doubleValue.value()); + element = Double.valueOf(doubleValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); // Check element's value - if (!element.equals(new Double(DOUB[j + i]))) { + if (!element.equals(Double.valueOf(DOUB[j + i]))) { log.complain("debuger FAILURE D2> " + j + " element " + "of array " + name + " was expected " + DOUB[j + i] + ", but returned " + element); @@ -375,12 +375,12 @@ public static int run(String argv[], PrintStream out) { testFailed = true; continue; } - element = new Float(floatValue.value()); + element = Float.valueOf(floatValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); // Check element's value - if (!element.equals(new Float(FLOAT[j + i]))) { + if (!element.equals(Float.valueOf(FLOAT[j + i]))) { log.complain("debuger FAILURE F2> " + j + " element " + "of array " + name + " was expected " + FLOAT[j + i] + ", but returned " diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002.java index 7ca97a15833..ae24619599b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -331,8 +331,8 @@ public static int run(String argv[], PrintStream out) { // Check element's value if (element != CHAR[j + i]) { - Character c = new Character('c'); - Integer n = new Integer(0); + Character c = Character.valueOf('c'); + Integer n = Integer.valueOf(0); String sReal = n.toHexString( c.getNumericValue(CHAR[j + i]) ); @@ -362,12 +362,12 @@ public static int run(String argv[], PrintStream out) { testFailed = true; continue; } - element = new Double(doubleValue.value()); + element = Double.valueOf(doubleValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); // Check element's value - if (!element.equals(new Double(DOUB[j + i]))) { + if (!element.equals(Double.valueOf(DOUB[j + i]))) { log.complain("debuger FAILURE D2> " + j + " element " + "of array " + name + " was expected " + DOUB[j + i] + ", but returned " + element); @@ -390,12 +390,12 @@ public static int run(String argv[], PrintStream out) { testFailed = true; continue; } - element = new Float(floatValue.value()); + element = Float.valueOf(floatValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); // Check element's value - if (!element.equals(new Float(FLOAT[j + i]))) { + if (!element.equals(Float.valueOf(FLOAT[j + i]))) { log.complain("debuger FAILURE F2> " + j + " element " + "of array " + name + " was expected " + FLOAT[j + i] + ", but returned " diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003.java index 60c83e998b3..3502d25a80e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii003.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,7 +105,7 @@ public static int run(String argv[], PrintStream out) { for (int i = 0; i < FIELD_NAME.length; i++) { Field field; String name = FIELD_NAME[i][0]; - Integer totalElements = new Integer(FIELD_NAME[i][1]); + Integer totalElements = Integer.valueOf(FIELD_NAME[i][1]); int lastElementIndex = totalElements.intValue() - 1; Value value; ArrayReference arrayRef; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004.java index b24ffddbf08..ec597298570 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/getValues_ii/getvaluesii004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,7 +105,7 @@ public static int run(String argv[], PrintStream out) { for (int i = 0; i < FIELD_NAME.length; i++) { Field field; String name = FIELD_NAME[i][0]; - Integer lengthOfArray = new Integer(FIELD_NAME[i][1]); + Integer lengthOfArray = Integer.valueOf(FIELD_NAME[i][1]); int length = lengthOfArray.intValue(); Value value; ArrayReference arrayRef; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001a.java index c7cb2f8a570..451034d66c3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/length/length001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,12 +87,12 @@ static interface Inter {} static Object O1[]={new Object(), new Object()}; static Object O2[][]={}; - static final Long LF1[]={new Long(1), new Long(-2), new Long(3)}; - static private Long LP1[][]={{new Long(1)}, {new Long(2)}, {new Long(3)}}; - static public Long LU1[][][]={{{new Long(1)}}, {{new Long(-2)}}}; - static protected Long LR1[][][][]={{{{new Long(1)}}}, {{{new Long(-2)}}}}; - static transient Long LT1[][][][][]={{{{{new Long(1)}}}}}; - static volatile Long LV1[][][][][][]={{{{{{new Long(1)}}}}}}; + static final Long LF1[]={Long.valueOf(1), Long.valueOf(-2), Long.valueOf(3)}; + static private Long LP1[][]={{Long.valueOf(1)}, {Long.valueOf(2)}, {Long.valueOf(3)}}; + static public Long LU1[][][]={{{Long.valueOf(1)}}, {{Long.valueOf(-2)}}}; + static protected Long LR1[][][][]={{{{Long.valueOf(1)}}}, {{{Long.valueOf(-2)}}}}; + static transient Long LT1[][][][][]={{{{{Long.valueOf(1)}}}}}; + static volatile Long LV1[][][][][][]={{{{{{Long.valueOf(1)}}}}}}; static final Inter EF1[]={}; static private Inter EP1[][]={{}}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001.java index dac39a77154..b3a734714f8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -495,7 +495,7 @@ public static int run(String argv[], PrintStream out) { testFailed = true; continue; } - dblSample = new Double(dblValue.value()); + dblSample = Double.valueOf(dblValue.value()); try { dblValue = (DoubleValue)valueNew; } catch (ClassCastException e) { @@ -505,7 +505,7 @@ public static int run(String argv[], PrintStream out) { testFailed = true; continue; } - dblNew = new Double(dblValue.value()); + dblNew = Double.valueOf(dblValue.value()); // Check two primitive values if (!dblNew.equals(dblSample)) { @@ -535,7 +535,7 @@ public static int run(String argv[], PrintStream out) { testFailed = true; continue; } - fltSample = new Float(fltValue.value()); + fltSample = Float.valueOf(fltValue.value()); try { fltValue = (FloatValue)valueNew; } catch (ClassCastException e) { @@ -545,7 +545,7 @@ public static int run(String argv[], PrintStream out) { testFailed = true; continue; } - fltNew = new Float(fltValue.value()); + fltNew = Float.valueOf(fltValue.value()); // Check two primitive values if (!fltNew.equals(fltSample)) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002.java index 66ace08d1c8..07d927847cd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValue/setvalue002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -218,7 +218,7 @@ public static int run(String argv[], PrintStream out) { for (int i = 0; i < FIELD_NAME.length; i++) { Field field; String name = FIELD_NAME[i][0]; - Integer totalElements = new Integer(FIELD_NAME[i][1]); + Integer totalElements = Integer.valueOf(FIELD_NAME[i][1]); String type = FIELD_NAME[i][2]; int lastElementIndex = totalElements.intValue() - 1; Value value; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001.java index bd3d891451b..4a1f6e6a413 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -805,11 +805,11 @@ public static int run(String argv[], PrintStream out) { continue; } - element = new Double(doubleValue.value()); + element = Double.valueOf(doubleValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); - if (!element.equals(new Double(DOUB[j]))) { + if (!element.equals(Double.valueOf(DOUB[j]))) { log.complain("debuger FAILURE D3> " + j + " element of " + "array " + name + " was expected " + DOUB[j] + ", but returned " + element); @@ -833,11 +833,11 @@ public static int run(String argv[], PrintStream out) { continue; } - element = new Float(floatValue.value()); + element = Float.valueOf(floatValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); - if (!element.equals(new Float(FLOAT[j]))) { + if (!element.equals(Float.valueOf(FLOAT[j]))) { log.complain("debuger FAILURE F3> " + j + " element of " + "array " + name + " was expected " + FLOAT[j] + ", but returned " + element); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002.java index 4e44a7de091..9d502ab0468 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_ilii/setvaluesilii002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -810,11 +810,11 @@ public static int run(String argv[], PrintStream out) { continue; } - element = new Double(doubleValue.value()); + element = Double.valueOf(doubleValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); - if (!element.equals(new Double(DOUB[j]))) { + if (!element.equals(Double.valueOf(DOUB[j]))) { log.complain("debuger FAILURE D3> " + j + " element of " + "array " + name + " was expected " + DOUB[j] + ", but returned " + element); @@ -838,11 +838,11 @@ public static int run(String argv[], PrintStream out) { continue; } - element = new Float(floatValue.value()); + element = Float.valueOf(floatValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); - if (!element.equals(new Float(FLOAT[j]))) { + if (!element.equals(Float.valueOf(FLOAT[j]))) { log.complain("debuger FAILURE F3> " + j + " element of " + "array " + name + " was expected " + FLOAT[j] + ", but returned " + element); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001.java index 323b8b06677..679cbb9a3da 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -600,11 +600,11 @@ public static int run(String argv[], PrintStream out) { continue; } - element = new Double(doubleValue.value()); + element = Double.valueOf(doubleValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); - if (!element.equals(new Double(DOUB[j]))) { + if (!element.equals(Double.valueOf(DOUB[j]))) { log.complain("debuger FAILURE D3> " + j + " element of " + "array " + name + " was expected " + DOUB[j] + ", but returned " + element); @@ -628,11 +628,11 @@ public static int run(String argv[], PrintStream out) { continue; } - element = new Float(floatValue.value()); + element = Float.valueOf(floatValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); - if (!element.equals(new Float(FLOAT[j]))) { + if (!element.equals(Float.valueOf(FLOAT[j]))) { log.complain("debuger FAILURE F3> " + j + " element of " + "array " + name + " was expected " + FLOAT[j] + ", but returned " + element); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002.java index d4f7f631581..a930c8b3035 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ArrayReference/setValues_l/setvaluesl002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -600,11 +600,11 @@ public static int run(String argv[], PrintStream out) { continue; } - element = new Double(doubleValue.value()); + element = Double.valueOf(doubleValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); - if (!element.equals(new Double(DOUB[j]))) { + if (!element.equals(Double.valueOf(DOUB[j]))) { log.complain("debuger FAILURE D3> " + j + " element of " + "array " + name + " was expected " + DOUB[j] + ", but returned " + element); @@ -628,11 +628,11 @@ public static int run(String argv[], PrintStream out) { continue; } - element = new Float(floatValue.value()); + element = Float.valueOf(floatValue.value()); log.display("debuger> " + i + " field has " + j + " element " + element); - if (!element.equals(new Float(FLOAT[j]))) { + if (!element.equals(Float.valueOf(FLOAT[j]))) { log.complain("debuger FAILURE F3> " + j + " element of " + "array " + name + " was expected " + FLOAT[j] + ", but returned " + element); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001a.java index 6281bfc52af..9bc458b9bb7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/reflectedType/reflectype001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,15 +47,15 @@ public class reflectype001a { // Classes must be loaded and linked, so all fields must be // initialized - Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; - Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; - Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; - Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; - Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; - Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; - Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; - String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; - Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + Boolean Z0 = Boolean.valueOf(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = Byte.valueOf((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = Character.valueOf('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = Double.valueOf(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = Float.valueOf(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = Integer.valueOf(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = Long.valueOf(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; // Interfaces must be loaded and linked, so classes that implement // interfaces must be initialized. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001a.java index 7764bff0268..7b55ae81e74 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ClassObjectReference/toString/tostring001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,16 +69,16 @@ public static void receiveSignal(String signal) { // Classes must be loaded and linked, so all fields must be // initialized - Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; - Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; - Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; - Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; - Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; - Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; - Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; - Short H0 = new Short((short)-1), H1[]={H0}, H2[][]={H1}; - String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; - Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + Boolean Z0 = Boolean.valueOf(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = Byte.valueOf((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = Character.valueOf('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = Double.valueOf(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = Float.valueOf(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = Integer.valueOf(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = Long.valueOf(-1l), L1[]={L0}, L2[][]={L1}; + Short H0 = Short.valueOf((short)-1), H1[]={H0}, H2[][]={H1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; // Interfaces must be loaded and linked, so classes that implement // interfaces must be initialized. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001.java index 3622fc90743..c0a11abe7b5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -219,7 +219,7 @@ class ClassOfFields { protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; - final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(999), LF1[]={LF0}, LF2[][]={LF1}; interface Inter {} Inter E0, E1[]={E0}, E2[][]={E1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001a.java index 8b16e12fa67..abe57ba7044 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,7 @@ class Class {} protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; - final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(999), LF1[]={LF0}, LF2[][]={LF1}; interface Inter {} Inter E0, E1[]={E0}, E2[][]={E1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002a.java index 1c17943fa6b..ec13c9ce3a8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,7 +64,7 @@ class Class {} protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; - final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(999), LF1[]={LF0}, LF2[][]={LF1}; interface Inter {} Inter E0, E1[]={E0}, E2[][]={E1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003a.java index 289fc8a03d2..e87ccf68e7c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,7 +98,7 @@ class Class {} protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; - final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(999), LF1[]={LF0}, LF2[][]={LF1}; interface Inter {} Inter E0, E1[]={E0}, E2[][]={E1}; @@ -146,7 +146,7 @@ class Class {} protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; - final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(999), LF1[]={LF0}, LF2[][]={LF1}; interface Inter {} Inter E0, E1[]={E0}, E2[][]={E1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005a.java index 9758af546f0..39986115e4c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/equals/equals005a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,7 +64,7 @@ class Class {} protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; - final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(999), LF1[]={LF0}, LF2[][]={LF1}; interface Inter {} Inter E0, E1[]={E0}, E2[][]={E1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001a.java index 722dcbc1128..e110fd696a1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/hashCode/hashcode001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,7 +64,7 @@ class Class {} protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; transient long LT0, LT1[]={LT0}, LT2[][]={LT1}; volatile long LV0, LV1[]={LV0}, LV2[][]={LV1}; - final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(999), LF1[]={LF0}, LF2[][]={LF1}; interface Inter {} Inter E0, E1[]={E0}, E2[][]={E1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001a.java index 225ae95ac25..e40a494d74b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isTransient/istrans001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,14 +88,14 @@ class Class {} public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; - final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(999), LF1[]={LF0}, LF2[][]={LF1}; transient static Long LS0T, LS1T[]={LS0T}, LS2T[][]={LS1T}; transient private Long LP0T, LP1T[]={LP0T}, LP2T[][]={LP1T}; transient public Long LU0T, LU1T[]={LU0T}, LU2T[][]={LU1T}; transient protected Long LR0T, LR1T[]={LR0T}, LR2T[][]={LR1T}; transient volatile Long LV0T, LV1T[]={LV0T}, LV2T[][]={LV1T}; - transient final Long LF0T = new Long(999), LF1T[]={LF0T}, + transient final Long LF0T = Long.valueOf(999), LF1T[]={LF0T}, LF2T[][]={LF1T}; interface Inter {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001a.java index 1fb0d769f40..d3e0ba6b106 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/isVolatile/isvol001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,7 @@ class Class {} public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; - final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(999), LF1[]={LF0}, LF2[][]={LF1}; volatile static Long LS0V, LS1V[]={LS0V}, LS2V[][]={LS1V}; volatile private Long LP0V, LP1V[]={LP0V}, LP2V[][]={LP1V}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002a.java index f06289d6038..732225f2cd2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/type/type002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,23 +56,23 @@ class type002aClassToCheck { // No array fields class Class {} Class X0 = new Class(); - Boolean Z0 = new Boolean(true); - Byte B0 = new Byte(Byte.MIN_VALUE); - Character C0 = new Character('\u00ff'); - Double D0 = new Double(1); - Float F0 = new Float(1f); - Integer I0 = new Integer(1); - Long L0 = new Long(1l); + Boolean Z0 = Boolean.valueOf(true); + Byte B0 = Byte.valueOf(Byte.MIN_VALUE); + Character C0 = Character.valueOf('\u00ff'); + Double D0 = Double.valueOf(1); + Float F0 = Float.valueOf(1f); + Integer I0 = Integer.valueOf(1); + Long L0 = Long.valueOf(1l); String S0 = new String(); Object O0 = new Object(); - static Long LS0 = new Long(1l); - private Long LP0 = new Long(1l); - public Long LU0 = new Long(1l); - protected Long LR0 = new Long(1l); - transient Long LT0 = new Long(1l); - volatile Long LV0 = new Long(1l); - final Long LF0 = new Long(1l); + static Long LS0 = Long.valueOf(1l); + private Long LP0 = Long.valueOf(1l); + public Long LU0 = Long.valueOf(1l); + protected Long LR0 = Long.valueOf(1l); + transient Long LT0 = Long.valueOf(1l); + volatile Long LV0 = Long.valueOf(1l); + final Long LF0 = Long.valueOf(1l); interface Inter {} static class InterClass implements Inter {} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001a.java index 3b29fc68206..a962d9c0d79 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Field/typeName/typename001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,7 +64,7 @@ class Class {} protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; - final Long LF0 = new Long(999), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(999), LF1[]={LF0}, LF2[][]={LF1}; interface Inter {} Inter E0, E1[]={E0}, E2[][]={E1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/toString/tostring001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/toString/tostring001a.java index a551705a311..f4e2a53b8ef 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/toString/tostring001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/LocalVariable/toString/tostring001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,14 +80,14 @@ public static void main (String argv[]) { long l0 = (long)-1, l1[] = {l0}, l2[][] = {l1}; short r0 = (short)-1, r1[] = {r0}, r2[][] = {r1}; - Boolean Z0 = new Boolean(false), Z1[] = {Z0}, Z2[][] = {Z1}; - Byte B0 = new Byte((byte)1), B1[] = {B0}, B2[][] = {B1}; - Character C0 = new Character('z'), C1[] = {C0}, C2[][] = {C1}; - Double D0 = new Double((double)1), D1[] = {D0}, D2[][] = {D1}; - Float F0 = new Float((float)1), F1[] = {F0}, F2[][] = {F1}; - Integer I0 = new Integer(1), I1[] = {I0}, I2[][] = {I1}; - Long L0 = new Long((long)1), L1[] = {L0}, L2[][] = {L1}; - Short R0 = new Short((short)1), R1[] = {R0}, R2[][] = {R1}; + Boolean Z0 = Boolean.valueOf(false), Z1[] = {Z0}, Z2[][] = {Z1}; + Byte B0 = Byte.valueOf((byte)1), B1[] = {B0}, B2[][] = {B1}; + Character C0 = Character.valueOf('z'), C1[] = {C0}, C2[][] = {C1}; + Double D0 = Double.valueOf((double)1), D1[] = {D0}, D2[][] = {D1}; + Float F0 = Float.valueOf((float)1), F1[] = {F0}, F2[][] = {F1}; + Integer I0 = Integer.valueOf(1), I1[] = {I0}, I2[][] = {I1}; + Long L0 = Long.valueOf((long)1), L1[] = {L0}, L2[][] = {L1}; + Short R0 = Short.valueOf((short)1), R1[] = {R0}, R2[][] = {R1}; String s0 = "string", s1[] = {s0}, s2[][] = {s1}; Object o0 = new Object(), o1[] = {o0}, o2[][] = {o1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isBridge/isbridge001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isBridge/isbridge001.java index 137865f8720..fba24de3a4c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isBridge/isbridge001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isBridge/isbridge001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -213,7 +213,7 @@ private int runThis(String args[], PrintStream out) { log.complain("TEST BUG: Integer.parseInt: caught " + e); return quitDebuggee(); } - boolean bridge = new Boolean(methods[i][idx][2]); + boolean bridge = Boolean.valueOf(methods[i][idx][2]); if (bridge == meth.isBridge()) log.display("\tCHECK PASSED: Method.isBridge() returns " + meth.isBridge() + " as expected\n"); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003/newclass/isobsolete003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003/newclass/isobsolete003b.java index 935c873cea3..58544450fee 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003/newclass/isobsolete003b.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003/newclass/isobsolete003b.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ public class isobsolete003b { static Integer foo(int i) { Integer j = null; try { - j = new Integer(new String(String.valueOf(i))); + j = Integer.valueOf(new String(String.valueOf(i))); } catch (NumberFormatException e) { } return j; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003b.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003b.java index 33145ec4c48..1b24c651d95 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003b.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/Method/isObsolete/isobsolete003b.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,6 @@ public class isobsolete003b { static Integer foo(int i) { int dummyInt = i; - return new Integer(i); // isobsolete003.brkpFooLineNumber + return Integer.valueOf(i); // isobsolete003.brkpFooLineNumber } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001a.java index acd9d43ee0c..04465c3e76b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/_itself_/mwevent001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -231,28 +231,28 @@ void initFields() { X0 = new Class(); X1 = new Class[] {X0}; X2 = new Class[][] {X1}; - Z0 = new Boolean(true); + Z0 = Boolean.valueOf(true); Z1 = new Boolean[] {Z0}; Z2 = new Boolean[][] {Z1}; - B0 = new Byte(java.lang.Byte.MIN_VALUE); + B0 = Byte.valueOf(java.lang.Byte.MIN_VALUE); B1 = new Byte[] {B0}; B2 = new Byte[][] {B1}; - C0 = new Character(java.lang.Character.MIN_VALUE); + C0 = Character.valueOf(java.lang.Character.MIN_VALUE); C1 = new Character[] {C0}; C2 = new Character[][]{C1}; - D0 = new Double(java.lang.Double.MIN_VALUE); + D0 = Double.valueOf(java.lang.Double.MIN_VALUE); D1 = new Double[] {D0}; D2 = new Double[][] {D1}; - F0 = new Float(java.lang.Float.MIN_VALUE); + F0 = Float.valueOf(java.lang.Float.MIN_VALUE); F1 = new Float[] {F0}; F2 = new Float[][] {F1}; - I0 = new Integer(java.lang.Integer.MIN_VALUE); + I0 = Integer.valueOf(java.lang.Integer.MIN_VALUE); I1 = new Integer[] {I0}; I2 = new Integer[][] {I1}; - L0 = new Long(java.lang.Long.MIN_VALUE); + L0 = Long.valueOf(java.lang.Long.MIN_VALUE); L1 = new Long[] {L0}; L2 = new Long[][] {L1}; - S0 = new Short(java.lang.Short.MIN_VALUE); + S0 = Short.valueOf(java.lang.Short.MIN_VALUE); S1 = new Short[] {S0}; S2 = new Short[][] {S1}; W0 = new String(); @@ -262,22 +262,22 @@ void initFields() { O1 = new Object[] {O0}; O2 = new Object[][] {O1}; - LS0 = new Long(java.lang.Long.MAX_VALUE); + LS0 = Long.valueOf(java.lang.Long.MAX_VALUE); LS1 = new Long[] {LS0}; LS2 = new Long[][] {LS1}; - LP0 = new Long(java.lang.Long.MAX_VALUE); + LP0 = Long.valueOf(java.lang.Long.MAX_VALUE); LP1 = new Long[] {LP0}; LP2 = new Long[][] {LP1}; - LU0 = new Long(java.lang.Long.MAX_VALUE); + LU0 = Long.valueOf(java.lang.Long.MAX_VALUE); LU1 = new Long[] {LU0}; LU2 = new Long[][] {LU1}; - LR0 = new Long(java.lang.Long.MAX_VALUE); + LR0 = Long.valueOf(java.lang.Long.MAX_VALUE); LR1 = new Long[] {LR0}; LR2 = new Long[][] {LR1}; - LT0 = new Long(java.lang.Long.MAX_VALUE); + LT0 = Long.valueOf(java.lang.Long.MAX_VALUE); LT1 = new Long[] {LT0}; LT2 = new Long[][] {LT1}; - LV0 = new Long(java.lang.Long.MAX_VALUE); + LV0 = Long.valueOf(java.lang.Long.MAX_VALUE); LV1 = new Long[] {LV0}; LV2 = new Long[][] {LV1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001a.java index 507bc3ab934..7300882ebfe 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -212,19 +212,19 @@ void initFields() { C0 = new Character(java.lang.Character.MIN_VALUE); C1 = new Character[] {C0}; C2 = new Character[][]{C1}; - D0 = new Double(java.lang.Double.MIN_VALUE); + D0 = Double.valueOf(java.lang.Double.MIN_VALUE); D1 = new Double[] {D0}; D2 = new Double[][] {D1}; - F0 = new Float(java.lang.Float.MIN_VALUE); + F0 = Float.valueOf(java.lang.Float.MIN_VALUE); F1 = new Float[] {F0}; F2 = new Float[][] {F1}; - I0 = new Integer(java.lang.Integer.MIN_VALUE); + I0 = Integer.valueOf(java.lang.Integer.MIN_VALUE); I1 = new Integer[] {I0}; I2 = new Integer[][] {I1}; - L0 = new Long(java.lang.Long.MIN_VALUE); + L0 = Long.valueOf(java.lang.Long.MIN_VALUE); L1 = new Long[] {L0}; L2 = new Long[][] {L1}; - S0 = new Short(java.lang.Short.MIN_VALUE); + S0 = Short.valueOf(java.lang.Short.MIN_VALUE); S1 = new Short[] {S0}; S2 = new Short[][] {S1}; W0 = new String(); @@ -234,22 +234,22 @@ void initFields() { O1 = new Object[] {O0}; O2 = new Object[][] {O1}; - LS0 = new Long(java.lang.Long.MAX_VALUE); + LS0 = Long.valueOf(java.lang.Long.MAX_VALUE); LS1 = new Long[] {LS0}; LS2 = new Long[][] {LS1}; - LP0 = new Long(java.lang.Long.MAX_VALUE); + LP0 = Long.valueOf(java.lang.Long.MAX_VALUE); LP1 = new Long[] {LP0}; LP2 = new Long[][] {LP1}; - LU0 = new Long(java.lang.Long.MAX_VALUE); + LU0 = Long.valueOf(java.lang.Long.MAX_VALUE); LU1 = new Long[] {LU0}; LU2 = new Long[][] {LU1}; - LR0 = new Long(java.lang.Long.MAX_VALUE); + LR0 = Long.valueOf(java.lang.Long.MAX_VALUE); LR1 = new Long[] {LR0}; LR2 = new Long[][] {LR1}; - LT0 = new Long(java.lang.Long.MAX_VALUE); + LT0 = Long.valueOf(java.lang.Long.MAX_VALUE); LT1 = new Long[] {LT0}; LT2 = new Long[][] {LT1}; - LV0 = new Long(java.lang.Long.MAX_VALUE); + LV0 = Long.valueOf(java.lang.Long.MAX_VALUE); LV1 = new Long[] {LV0}; LV2 = new Long[][] {LV1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002a.java index 78fdd9a550e..f77062bb6e3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ModificationWatchpointEvent/valueToBe/valuetobe002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -201,19 +201,19 @@ void initFields(boolean flag) { C0 = flag ? C0 : new Character(java.lang.Character.MIN_VALUE); C1 = flag ? C1 : new Character[] {C0}; C2 = flag ? C2 : new Character[][]{C1}; - D0 = flag ? D0 : new Double(java.lang.Double.MIN_VALUE); + D0 = flag ? D0 : Double.valueOf(java.lang.Double.MIN_VALUE); D1 = flag ? D1 : new Double[] {D0}; D2 = flag ? D2 : new Double[][] {D1}; - F0 = flag ? F0 : new Float(java.lang.Float.MIN_VALUE); + F0 = flag ? F0 : Float.valueOf(java.lang.Float.MIN_VALUE); F1 = flag ? F1 : new Float[] {F0}; F2 = flag ? F2 : new Float[][] {F1}; - I0 = flag ? I0 : new Integer(java.lang.Integer.MIN_VALUE); + I0 = flag ? I0 : Integer.valueOf(java.lang.Integer.MIN_VALUE); I1 = flag ? I1 : new Integer[] {I0}; I2 = flag ? I2 : new Integer[][] {I1}; - L0 = flag ? L0 : new Long(java.lang.Long.MIN_VALUE); + L0 = flag ? L0 : Long.valueOf(java.lang.Long.MIN_VALUE); L1 = flag ? L1 : new Long[] {L0}; L2 = flag ? L2 : new Long[][] {L1}; - S0 = flag ? S0 : new Short(java.lang.Short.MIN_VALUE); + S0 = flag ? S0 : Short.valueOf(java.lang.Short.MIN_VALUE); S1 = flag ? S1 : new Short[] {S0}; S2 = flag ? S2 : new Short[][] {S1}; W0 = flag ? W0 : new String(); @@ -223,22 +223,22 @@ void initFields(boolean flag) { O1 = flag ? O1 : new Object[] {O0}; O2 = flag ? O2 : new Object[][] {O1}; - LS0 = flag ? LS0 : new Long(java.lang.Long.MAX_VALUE); + LS0 = flag ? LS0 : Long.valueOf(java.lang.Long.MAX_VALUE); LS1 = flag ? LS1 : new Long[] {LS0}; LS2 = flag ? LS2 : new Long[][] {LS1}; - LP0 = flag ? LP0 : new Long(java.lang.Long.MAX_VALUE); + LP0 = flag ? LP0 : Long.valueOf(java.lang.Long.MAX_VALUE); LP1 = flag ? LP1 : new Long[] {LP0}; LP2 = flag ? LP2 : new Long[][] {LP1}; - LU0 = flag ? LU0 : new Long(java.lang.Long.MAX_VALUE); + LU0 = flag ? LU0 : Long.valueOf(java.lang.Long.MAX_VALUE); LU1 = flag ? LU1 : new Long[] {LU0}; LU2 = flag ? LU2 : new Long[][] {LU1}; - LR0 = flag ? LR0 : new Long(java.lang.Long.MAX_VALUE); + LR0 = flag ? LR0 : Long.valueOf(java.lang.Long.MAX_VALUE); LR1 = flag ? LR1 : new Long[] {LR0}; LR2 = flag ? LR2 : new Long[][] {LR1}; - LT0 = flag ? LT0 : new Long(java.lang.Long.MAX_VALUE); + LT0 = flag ? LT0 : Long.valueOf(java.lang.Long.MAX_VALUE); LT1 = flag ? LT1 : new Long[] {LT0}; LT2 = flag ? LT2 : new Long[][] {LT1}; - LV0 = flag ? LV0 : new Long(java.lang.Long.MAX_VALUE); + LV0 = flag ? LV0 : Long.valueOf(java.lang.Long.MAX_VALUE); LV1 = flag ? LV1 : new Long[] {LV0}; LV2 = flag ? LV2 : new Long[][] {LV1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields005t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields005t.java index abe41263ecd..0cdd9627b72 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields005t.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allFields/allfields005t.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,14 +71,14 @@ public static int run(String args[]) { static Class longCls = Long.TYPE; static Class shortCls = Short.TYPE; - static Boolean boolClsArr[] = {new Boolean(false)}; - static Byte byteClsArr[] = {new Byte((byte) 127)}; - static Character charClsArr[] = {new Character('a')}; - static Double doubleClsArr[] = {new Double(6.2D)}; - static Float floatClsArr[] = {new Float(5.1F)}; - static Integer intClsArr[] = {new Integer(2147483647)}; - static Long longClsArr[] = {new Long(9223372036854775807L)}; - static Short shortClsArr[] = {new Short((short) -32768)}; + static Boolean boolClsArr[] = {Boolean.valueOf(false)}; + static Byte byteClsArr[] = {Byte.valueOf((byte) 127)}; + static Character charClsArr[] = {Character.valueOf('a')}; + static Double doubleClsArr[] = {Double.valueOf(6.2D)}; + static Float floatClsArr[] = {Float.valueOf(5.1F)}; + static Integer intClsArr[] = {Integer.valueOf(2147483647)}; + static Long longClsArr[] = {Long.valueOf(9223372036854775807L)}; + static Short shortClsArr[] = {Short.valueOf((short) -32768)}; static boolean boolArr[] = {true}; static byte byteArr[] = {Byte.MAX_VALUE}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations002t.java index 311a8e1df84..ad2051478e1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations002t.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations/alllinelocations002t.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,14 +70,14 @@ public static int run(String args[]) { static Class longCls = Long.TYPE; static Class shortCls = Short.TYPE; - static Boolean boolClsArr[] = {new Boolean(false)}; - static Byte byteClsArr[] = {new Byte((byte) 127)}; - static Character charClsArr[] = {new Character('a')}; - static Double doubleClsArr[] = {new Double(6.2D)}; - static Float floatClsArr[] = {new Float(5.1F)}; - static Integer intClsArr[] = {new Integer(2147483647)}; - static Long longClsArr[] = {new Long(9223372036854775807L)}; - static Short shortClsArr[] = {new Short((short) -32768)}; + static Boolean boolClsArr[] = {Boolean.valueOf(false)}; + static Byte byteClsArr[] = {Byte.valueOf((byte) 127)}; + static Character charClsArr[] = {Character.valueOf('a')}; + static Double doubleClsArr[] = {Double.valueOf(6.2D)}; + static Float floatClsArr[] = {Float.valueOf(5.1F)}; + static Integer intClsArr[] = {Integer.valueOf(2147483647)}; + static Long longClsArr[] = {Long.valueOf(9223372036854775807L)}; + static Short shortClsArr[] = {Short.valueOf((short) -32768)}; static boolean boolArr[] = {true}; static byte byteArr[] = {Byte.MAX_VALUE}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss002t.java index b155b223bc0..845268c46f7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss002t.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allLineLocations_ss/alllinelocations_ss002t.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,14 +70,14 @@ public static int run(String args[]) { static Class longCls = Long.TYPE; static Class shortCls = Short.TYPE; - static Boolean boolClsArr[] = {new Boolean(false)}; - static Byte byteClsArr[] = {new Byte((byte) 127)}; - static Character charClsArr[] = {new Character('a')}; - static Double doubleClsArr[] = {new Double(6.2D)}; - static Float floatClsArr[] = {new Float(5.1F)}; - static Integer intClsArr[] = {new Integer(2147483647)}; - static Long longClsArr[] = {new Long(9223372036854775807L)}; - static Short shortClsArr[] = {new Short((short) -32768)}; + static Boolean boolClsArr[] = {Boolean.valueOf(false)}; + static Byte byteClsArr[] = {Byte.valueOf((byte) 127)}; + static Character charClsArr[] = {Character.valueOf('a')}; + static Double doubleClsArr[] = {Double.valueOf(6.2D)}; + static Float floatClsArr[] = {Float.valueOf(5.1F)}; + static Integer intClsArr[] = {Integer.valueOf(2147483647)}; + static Long longClsArr[] = {Long.valueOf(9223372036854775807L)}; + static Short shortClsArr[] = {Short.valueOf((short) -32768)}; static boolean boolArr[] = {true}; static byte byteArr[] = {Byte.MAX_VALUE}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods005t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods005t.java index 19119b26260..abb43d64a52 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods005t.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/allMethods/allmethods005t.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,14 +71,14 @@ public static int run(String args[]) { static Class longCls = Long.TYPE; static Class shortCls = Short.TYPE; - static Boolean boolClsArr[] = {new Boolean(false)}; - static Byte byteClsArr[] = {new Byte((byte) 127)}; - static Character charClsArr[] = {new Character('a')}; - static Double doubleClsArr[] = {new Double(6.2D)}; - static Float floatClsArr[] = {new Float(5.1F)}; - static Integer intClsArr[] = {new Integer(2147483647)}; - static Long longClsArr[] = {new Long(9223372036854775807L)}; - static Short shortClsArr[] = {new Short((short) -32768)}; + static Boolean boolClsArr[] = {Boolean.valueOf(false)}; + static Byte byteClsArr[] = {Byte.valueOf((byte) 127)}; + static Character charClsArr[] = {Character.valueOf('a')}; + static Double doubleClsArr[] = {Double.valueOf(6.2D)}; + static Float floatClsArr[] = {Float.valueOf(5.1F)}; + static Integer intClsArr[] = {Integer.valueOf(2147483647)}; + static Long longClsArr[] = {Long.valueOf(9223372036854775807L)}; + static Short shortClsArr[] = {Short.valueOf((short) -32768)}; static boolean boolArr[] = {true}; static byte byteArr[] = {Byte.MAX_VALUE}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001a.java index baac6343384..8c9f3d6d05e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/classObject/classobj001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,15 +47,15 @@ public class classobj001a { // Classes must be loaded and linked, so all fields must be // initialized - Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; - Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; - Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; - Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; - Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; - Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; - Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; - String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; - Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + Boolean Z0 = Boolean.valueOf(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = Byte.valueOf((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = Character.valueOf('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = Double.valueOf(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = Float.valueOf(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = Integer.valueOf(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = Long.valueOf(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; // Interfaces must be loaded and linked, so classes that implement // interfaces must be initialized. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001a.java index bc74f002d8c..75551cc3546 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/equals/equals001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,15 +48,15 @@ public class equals001a { // Classes must be loaded and linked, so all fields must be // initialized - Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; - Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; - Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; - Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; - Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; - Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; - Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; - String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; - Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + Boolean Z0 = Boolean.valueOf(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = Byte.valueOf((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = Character.valueOf('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = Double.valueOf(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = Float.valueOf(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = Integer.valueOf(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = Long.valueOf(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; static class s_class {} s_class s_class_0 = new s_class(), s_class_1[]={s_class_0}, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields005t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields005t.java index 52f9efd8391..5e9d78af0ec 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields005t.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/fields/fields005t.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,14 +71,14 @@ public static int run(String args[]) { static Class longCls = Long.TYPE; static Class shortCls = Short.TYPE; - static Boolean boolClsArr[] = {new Boolean(false)}; - static Byte byteClsArr[] = {new Byte((byte) 127)}; - static Character charClsArr[] = {new Character('a')}; - static Double doubleClsArr[] = {new Double(6.2D)}; - static Float floatClsArr[] = {new Float(5.1F)}; - static Integer intClsArr[] = {new Integer(2147483647)}; - static Long longClsArr[] = {new Long(9223372036854775807L)}; - static Short shortClsArr[] = {new Short((short) -32768)}; + static Boolean boolClsArr[] = {Boolean.valueOf(false)}; + static Byte byteClsArr[] = {Byte.valueOf((byte) 127)}; + static Character charClsArr[] = {Character.valueOf('a')}; + static Double doubleClsArr[] = {Double.valueOf(6.2D)}; + static Float floatClsArr[] = {Float.valueOf(5.1F)}; + static Integer intClsArr[] = {Integer.valueOf(2147483647)}; + static Long longClsArr[] = {Long.valueOf(9223372036854775807L)}; + static Short shortClsArr[] = {Short.valueOf((short) -32768)}; static boolean boolArr[] = {true}; static byte byteArr[] = {Byte.MAX_VALUE}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001a.java index 4b402d515bc..723035860f7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/hashCode/hashcode001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,15 +48,15 @@ public class hashcode001a { // Classes must be loaded and linked, so all fields must be // initialized - Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; - Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; - Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; - Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; - Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; - Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; - Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; - String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; - Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + Boolean Z0 = Boolean.valueOf(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = Byte.valueOf((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = Character.valueOf('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = Double.valueOf(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = Float.valueOf(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = Integer.valueOf(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = Long.valueOf(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; static class s_class {} s_class s_class_0 = new s_class(), s_class_1[]={s_class_0}, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001a.java index 7c9dc66003c..3006056fc8b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isFinal/isfinal001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -151,14 +151,14 @@ interface NestedIface { long ln[][][][] = {{{{0}}}}; short sh[][][][] = {{{{0}}}}; - Boolean blBl = new Boolean(true); - Byte btBt = new Byte((byte)1); - Character chCh = new Character('c'); - Double dbDb = new Double(0); - Float flFl = new Float(0.0f); - Integer inIn = new Integer(0); - Long lnLn = new Long(0); - Short shSh = new Short((short)1); + Boolean blBl = Boolean.valueOf(true); + Byte btBt = Byte.valueOf((byte)1); + Character chCh = Character.valueOf('c'); + Double dbDb = Double.valueOf(0); + Float flFl = Float.valueOf(0.0f); + Integer inIn = Integer.valueOf(0); + Long lnLn = Long.valueOf(0); + Short shSh = Short.valueOf((short)1); } interface OuterIface { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001a.java index 2065d1f7e5f..f9f7e235c39 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/isStatic/isstatic001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,14 +149,14 @@ static class StaticNestedClass { short sh[][][][] = {{{{0}}}}; - Boolean blBl = new Boolean(true); - Byte btBt = new Byte((byte)1); - Character chCh = new Character('c'); - Double dbDb = new Double(0); - Float flFl = new Float(0.0f); - Integer inIn = new Integer(0); - Long lnLn = new Long(0); - Short shSh = new Short((short)1); + Boolean blBl = Boolean.valueOf(true); + Byte btBt = Byte.valueOf((byte)1); + Character chCh = Character.valueOf('c'); + Double dbDb = Double.valueOf(0); + Float flFl = Float.valueOf(0.0f); + Integer inIn = Integer.valueOf(0); + Long lnLn = Long.valueOf(0); + Short shSh = Short.valueOf((short)1); } interface isstatic001aOuterIface { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i002t.java index 1ea005a62bc..88869146a38 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i002t.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_i/locationsofline_i002t.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,14 +70,14 @@ public static int run(String args[]) { static Class longCls = Long.TYPE; static Class shortCls = Short.TYPE; - static Boolean boolClsArr[] = {new Boolean(false)}; - static Byte byteClsArr[] = {new Byte((byte) 127)}; - static Character charClsArr[] = {new Character('a')}; - static Double doubleClsArr[] = {new Double(6.2D)}; - static Float floatClsArr[] = {new Float(5.1F)}; - static Integer intClsArr[] = {new Integer(2147483647)}; - static Long longClsArr[] = {new Long(9223372036854775807L)}; - static Short shortClsArr[] = {new Short((short) -32768)}; + static Boolean boolClsArr[] = {Boolean.valueOf(false)}; + static Byte byteClsArr[] = {Byte.valueOf((byte) 127)}; + static Character charClsArr[] = {Character.valueOf('a')}; + static Double doubleClsArr[] = {Double.valueOf(6.2D)}; + static Float floatClsArr[] = {Float.valueOf(5.1F)}; + static Integer intClsArr[] = {Integer.valueOf(2147483647)}; + static Long longClsArr[] = {Long.valueOf(9223372036854775807L)}; + static Short shortClsArr[] = {Short.valueOf((short) -32768)}; static boolean boolArr[] = {true}; static byte byteArr[] = {Byte.MAX_VALUE}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi002t.java index cc9a946b3c3..d6079e88580 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi002t.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/locationsOfLine_ssi/locationsofline_ssi002t.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,14 +70,14 @@ public static int run(String args[]) { static Class longCls = Long.TYPE; static Class shortCls = Short.TYPE; - static Boolean boolClsArr[] = {new Boolean(false)}; - static Byte byteClsArr[] = {new Byte((byte) 127)}; - static Character charClsArr[] = {new Character('a')}; - static Double doubleClsArr[] = {new Double(6.2D)}; - static Float floatClsArr[] = {new Float(5.1F)}; - static Integer intClsArr[] = {new Integer(2147483647)}; - static Long longClsArr[] = {new Long(9223372036854775807L)}; - static Short shortClsArr[] = {new Short((short) -32768)}; + static Boolean boolClsArr[] = {Boolean.valueOf(false)}; + static Byte byteClsArr[] = {Byte.valueOf((byte) 127)}; + static Character charClsArr[] = {Character.valueOf('a')}; + static Double doubleClsArr[] = {Double.valueOf(6.2D)}; + static Float floatClsArr[] = {Float.valueOf(5.1F)}; + static Integer intClsArr[] = {Integer.valueOf(2147483647)}; + static Long longClsArr[] = {Long.valueOf(9223372036854775807L)}; + static Short shortClsArr[] = {Short.valueOf((short) -32768)}; static boolean boolArr[] = {true}; static byte byteArr[] = {Byte.MAX_VALUE}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods005t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods005t.java index 21bcf9f0daa..327a95e401f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods005t.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/methods/methods005t.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,14 +71,14 @@ public static int run(String args[]) { static Class longCls = Long.TYPE; static Class shortCls = Short.TYPE; - static Boolean boolClsArr[] = {new Boolean(false)}; - static Byte byteClsArr[] = {new Byte((byte) 127)}; - static Character charClsArr[] = {new Character('a')}; - static Double doubleClsArr[] = {new Double(6.2D)}; - static Float floatClsArr[] = {new Float(5.1F)}; - static Integer intClsArr[] = {new Integer(2147483647)}; - static Long longClsArr[] = {new Long(9223372036854775807L)}; - static Short shortClsArr[] = {new Short((short) -32768)}; + static Boolean boolClsArr[] = {Boolean.valueOf(false)}; + static Byte byteClsArr[] = {Byte.valueOf((byte) 127)}; + static Character charClsArr[] = {Character.valueOf('a')}; + static Double doubleClsArr[] = {Double.valueOf(6.2D)}; + static Float floatClsArr[] = {Float.valueOf(5.1F)}; + static Integer intClsArr[] = {Integer.valueOf(2147483647)}; + static Long longClsArr[] = {Long.valueOf(9223372036854775807L)}; + static Short shortClsArr[] = {Short.valueOf((short) -32768)}; static boolean boolArr[] = {true}; static byte byteArr[] = {Byte.MAX_VALUE}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001a.java index c547460c0ac..7525f8b96e9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/name/name001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,15 +48,15 @@ public class name001a { // Classes must be loaded and linked, so all fields must be // initialized - Boolean Z0 = new Boolean(true), Z1[]={Z0}, Z2[][]={Z1}; - Byte B0 = new Byte((byte)1), B1[]={B0}, B2[][]={B1}; - Character C0 = new Character('\u00ff'), C1[]={C0}, C2[][]={C1}; - Double D0 = new Double(1.0), D1[]={D0}, D2[][]={D1}; - Float F0 = new Float(1.0f), F1[]={F0}, F2[][]={F1}; - Integer I0 = new Integer(-1), I1[]={I0}, I2[][]={I1}; - Long L0 = new Long(-1l), L1[]={L0}, L2[][]={L1}; - String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; - Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; + Boolean Z0 = Boolean.valueOf(true), Z1[]={Z0}, Z2[][]={Z1}; + Byte B0 = Byte.valueOf((byte)1), B1[]={B0}, B2[][]={B1}; + Character C0 = Character.valueOf('\u00ff'), C1[]={C0}, C2[][]={C1}; + Double D0 = Double.valueOf(1.0), D1[]={D0}, D2[][]={D1}; + Float F0 = Float.valueOf(1.0f), F1[]={F0}, F2[][]={F1}; + Integer I0 = Integer.valueOf(-1), I1[]={I0}, I2[][]={I1}; + Long L0 = Long.valueOf(-1l), L1[]={L0}, L2[][]={L1}; + String S0 = new String("4434819"), S1[]={S0}, S2[][]={S1}; + Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; static class s_class {} s_class s_class_0 = new s_class(), s_class_1[]={s_class_0}, diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames002t.java index 3064adec59a..7ed7f98e706 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames002t.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourceNames/sourcenames002t.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,14 +88,14 @@ private int sourcenames002trunIt(String args[]) { // arrays used to check AbsentInformationException throwing // in the debugger - Boolean boolClsArr[] = {new Boolean(false)}; - Byte byteClsArr[] = {new Byte((byte) 127)}; - Character charClsArr[] = {new Character('a')}; - Double doubleClsArr[] = {new Double(6.2D)}; - Float floatClsArr[] = {new Float(5.1F)}; - Integer intClsArr[] = {new Integer(2147483647)}; - Long longClsArr[] = {new Long(9223372036854775807L)}; - Short shortClsArr[] = {new Short((short) -32768)}; + Boolean boolClsArr[] = {Boolean.valueOf(false)}; + Byte byteClsArr[] = {Byte.valueOf((byte) 127)}; + Character charClsArr[] = {Character.valueOf('a')}; + Double doubleClsArr[] = {Double.valueOf(6.2D)}; + Float floatClsArr[] = {Float.valueOf(5.1F)}; + Integer intClsArr[] = {Integer.valueOf(2147483647)}; + Long longClsArr[] = {Long.valueOf(9223372036854775807L)}; + Short shortClsArr[] = {Short.valueOf((short) -32768)}; boolean boolArr[] = {boolVal}; byte byteArr[] = {byteVal}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths002t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths002t.java index c0aa919e0ad..afd87d49bb9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths002t.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/sourcePaths/sourcepaths002t.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,14 +73,14 @@ public static int run(String args[]) { // arrays used to check AbsentInformationException throwing // in the debugger - static Boolean boolClsArr[] = {new Boolean(false)}; - static Byte byteClsArr[] = {new Byte((byte) 127)}; - static Character charClsArr[] = {new Character('a')}; - static Double doubleClsArr[] = {new Double(6.2D)}; - static Float floatClsArr[] = {new Float(5.1F)}; - static Integer intClsArr[] = {new Integer(2147483647)}; - static Long longClsArr[] = {new Long(9223372036854775807L)}; - static Short shortClsArr[] = {new Short((short) -32768)}; + static Boolean boolClsArr[] = {Boolean.valueOf(false)}; + static Byte byteClsArr[] = {Byte.valueOf((byte) 127)}; + static Character charClsArr[] = {Character.valueOf('a')}; + static Double doubleClsArr[] = {Double.valueOf(6.2D)}; + static Float floatClsArr[] = {Float.valueOf(5.1F)}; + static Integer intClsArr[] = {Integer.valueOf(2147483647)}; + static Long longClsArr[] = {Long.valueOf(9223372036854775807L)}; + static Short shortClsArr[] = {Short.valueOf((short) -32768)}; static boolean boolArr[] = {true}; static byte byteArr[] = {Byte.MAX_VALUE}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield005t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield005t.java index d1c434d245e..c8f245772eb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield005t.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleFields/visibfield005t.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,14 +71,14 @@ public static int run(String args[]) { static Class longCls = Long.TYPE; static Class shortCls = Short.TYPE; - static Boolean boolClsArr[] = {new Boolean(false)}; - static Byte byteClsArr[] = {new Byte((byte) 127)}; - static Character charClsArr[] = {new Character('a')}; - static Double doubleClsArr[] = {new Double(6.2D)}; - static Float floatClsArr[] = {new Float(5.1F)}; - static Integer intClsArr[] = {new Integer(2147483647)}; - static Long longClsArr[] = {new Long(9223372036854775807L)}; - static Short shortClsArr[] = {new Short((short) -32768)}; + static Boolean boolClsArr[] = {Boolean.valueOf(false)}; + static Byte byteClsArr[] = {Byte.valueOf((byte) 127)}; + static Character charClsArr[] = {Character.valueOf('a')}; + static Double doubleClsArr[] = {Double.valueOf(6.2D)}; + static Float floatClsArr[] = {Float.valueOf(5.1F)}; + static Integer intClsArr[] = {Integer.valueOf(2147483647)}; + static Long longClsArr[] = {Long.valueOf(9223372036854775807L)}; + static Short shortClsArr[] = {Short.valueOf((short) -32768)}; static boolean boolArr[] = {true}; static byte byteArr[] = {Byte.MAX_VALUE}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod006t.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod006t.java index 371916d8297..8d00ca6990a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod006t.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ReferenceType/visibleMethods/visibmethod006t.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,14 +71,14 @@ public static int run(String args[]) { static Class longCls = Long.TYPE; static Class shortCls = Short.TYPE; - static Boolean boolClsArr[] = {new Boolean(false)}; - static Byte byteClsArr[] = {new Byte((byte) 127)}; - static Character charClsArr[] = {new Character('a')}; - static Double doubleClsArr[] = {new Double(6.2D)}; - static Float floatClsArr[] = {new Float(5.1F)}; - static Integer intClsArr[] = {new Integer(2147483647)}; - static Long longClsArr[] = {new Long(9223372036854775807L)}; - static Short shortClsArr[] = {new Short((short) -32768)}; + static Boolean boolClsArr[] = {Boolean.valueOf(false)}; + static Byte byteClsArr[] = {Byte.valueOf((byte) 127)}; + static Character charClsArr[] = {Character.valueOf('a')}; + static Double doubleClsArr[] = {Double.valueOf(6.2D)}; + static Float floatClsArr[] = {Float.valueOf(5.1F)}; + static Integer intClsArr[] = {Integer.valueOf(2147483647)}; + static Long longClsArr[] = {Long.valueOf(9223372036854775807L)}; + static Short shortClsArr[] = {Short.valueOf((short) -32768)}; static boolean boolArr[] = {true}; static byte byteArr[] = {Byte.MAX_VALUE}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype001a.java index 4606386d964..32891fef94a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,7 +77,7 @@ class MainClass { Class X0, X1[]={X0}, X2[][]={X1}; Object O0, O1[]={O0}, O2[][]={O1}; - final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(1), LF1[]={LF0}, LF2[][]={LF1}; private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; @@ -115,9 +115,9 @@ interface MainInter { Class X0 = new Class(), X1[]={X0}, X2[][]={X1}; Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; - final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; - public Long LU0 = new Long(1), LU1[]={LU0}, LU2[][]={LU1}; - static Long L0S = new Long(1), L1S[]={L0S}, L2S[][]={L1S}; + final Long LF0 = Long.valueOf(1), LF1[]={LF0}, LF2[][]={LF1}; + public Long LU0 = Long.valueOf(1), LU1[]={LU0}, LU2[][]={LU1}; + static Long L0S = Long.valueOf(1), L1S[]={L0S}, L2S[][]={L1S}; Inter E0 = null, E1[]={E0}, E2[][]={E1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002a.java index 1be71f70fd3..65c5d4c08e2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype002a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,7 +82,7 @@ class decltype002aMainClass { decltype002aClass X0, X1[]={X0}, X2[][]={X1}; Object O0, O1[]={O0}, O2[][]={O1}; - final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(1), LF1[]={LF0}, LF2[][]={LF1}; private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; @@ -124,9 +124,9 @@ interface decltype002aMainInter { decltype002aClass X0 = new decltype002aClass(), X1[]={X0}, X2[][]={X1}; Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; - final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; - public Long LU0 = new Long(1), LU1[]={LU0}, LU2[][]={LU1}; - static Long L0S = new Long(1), L1S[]={L0S}, L2S[][]={L1S}; + final Long LF0 = Long.valueOf(1), LF1[]={LF0}, LF2[][]={LF1}; + public Long LU0 = Long.valueOf(1), LU1[]={LU0}, LU2[][]={LU1}; + static Long L0S = Long.valueOf(1), L1S[]={L0S}, L2S[][]={L1S}; decltype002aInter E0 = null, E1[]={E0}, E2[][]={E1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003a.java index e8387e5ad70..64c9c846580 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -79,7 +79,7 @@ class decltype003aOverridenClass extends decltype003aMainClass { decltype003aClass X0, X1[]={X0}, X2[][]={X1}; Object O0, O1[]={O0}, O2[][]={O1}; - final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(1), LF1[]={LF0}, LF2[][]={LF1}; private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; @@ -119,7 +119,7 @@ class decltype003aMainClass { decltype003aClass X0, X1[]={X0}, X2[][]={X1}; Object O0, O1[]={O0}, O2[][]={O1}; - final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(1), LF1[]={LF0}, LF2[][]={LF1}; private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; @@ -159,9 +159,9 @@ interface decltype003aOverridenInter extends decltype003aMainInter { decltype003aClass X0 = new decltype003aClass(), X1[]={X0}, X2[][]={X1}; Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; - final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; - public Long LU0 = new Long(1), LU1[]={LU0}, LU2[][]={LU1}; - static Long L0S = new Long(1), L1S[]={L0S}, L2S[][]={L1S}; + final Long LF0 = Long.valueOf(1), LF1[]={LF0}, LF2[][]={LF1}; + public Long LU0 = Long.valueOf(1), LU1[]={LU0}, LU2[][]={LU1}; + static Long L0S = Long.valueOf(1), L1S[]={L0S}, L2S[][]={L1S}; decltype003aInter E0 = null, E1[]={E0}, E2[][]={E1}; @@ -187,9 +187,9 @@ interface decltype003aMainInter { decltype003aClass X0 = new decltype003aClass(), X1[]={X0}, X2[][]={X1}; Object O0 = new Object(), O1[]={O0}, O2[][]={O1}; - final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; - public Long LU0 = new Long(1), LU1[]={LU0}, LU2[][]={LU1}; - static Long L0S = new Long(1), L1S[]={L0S}, L2S[][]={L1S}; + final Long LF0 = Long.valueOf(1), LF1[]={LF0}, LF2[][]={LF1}; + public Long LU0 = Long.valueOf(1), LU1[]={LU0}, LU2[][]={LU1}; + static Long L0S = Long.valueOf(1), L1S[]={L0S}, L2S[][]={L1S}; decltype003aInter E0 = null, E1[]={E0}, E2[][]={E1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007a.java index 71a185a04eb..05abe315509 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype007a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ class decltype007aMainClass { static long[] cl = new long[10]; static { ci = 1; } - static { cL = new Long(1l); } + static { cL = Long.valueOf(1l); } static { for (int i = 0; i < 10; i++) { cl[i] = (long)i; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008a.java index beee2e30f08..31af4a8f6c7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/declaringType/decltype008a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,13 +54,13 @@ public static void main (String argv[]) { class decltype008aOtherClass extends decltype008aMainClass { // All contructors from decltype008aOtherClass starts with reference to String object public decltype008aOtherClass(String S, float f) { - super(new Long(1), f); + super(Long.valueOf(1), f); }; private decltype008aOtherClass(String S, Object obj){ - super(new Long(1), obj); + super(Long.valueOf(1), obj); }; protected decltype008aOtherClass(String S, long[] l) { - super(new Long(1), l); + super(Long.valueOf(1), l); }; static double cd; @@ -87,7 +87,7 @@ class decltype008aMainClass { static long[] cl = new long[10]; static { ci = 1; } - static { cL = new Long(1l); } + static { cL = Long.valueOf(1l); } static { for (int i = 0; i < 10; i++) { cl[i] = (long)i; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001a.java index 4faa54b2e94..7fbe1764c1b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -100,11 +100,11 @@ interface isfinal001aInter {} transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; - final static Long LS0F = new Long(1), LS1F[]={LS0F}, LS2F[][]={LS1F}; - final private Long LP0F = new Long(1), LP1F[]={LP0F}, LP2F[][]={LP1F}; - final public Long LU0F = new Long(1), LU1F[]={LU0F}, LU2F[][]={LU1F}; - final protected Long LR0F = new Long(1), LR1F[]={LR0F}, LR2F[][]={LR1F}; - final transient Long LT0F = new Long(1), LT1F[]={LT0F}, LT2F[][]={LT1F}; + final static Long LS0F = Long.valueOf(1), LS1F[]={LS0F}, LS2F[][]={LS1F}; + final private Long LP0F = Long.valueOf(1), LP1F[]={LP0F}, LP2F[][]={LP1F}; + final public Long LU0F = Long.valueOf(1), LU1F[]={LU0F}, LU2F[][]={LU1F}; + final protected Long LR0F = Long.valueOf(1), LR1F[]={LR0F}, LR2F[][]={LR1F}; + final transient Long LT0F = Long.valueOf(1), LT1F[]={LT0F}, LT2F[][]={LT1F}; isfinal001aInter E0, E1[]={E0}, E2[][]={E1}; final isfinal001aInter E0F = null, E1F[]={E0F}, E2F[][]={E1F}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003a.java index 8dbdebc426e..748c9558940 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isFinal/isfinal003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ class isfinal003aClassToCheck extends isfinal003aSuperClass { static long[] cl = new long[10]; static { ci = 1; } - static { cL = new Long(1l); } + static { cL = Long.valueOf(1l); } static { for (int i = 0; i < 10; i++) { cl[i] = (long)i; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001a.java index 49cd0e814ef..98efa7eae02 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -94,14 +94,14 @@ interface Inter {} static Class X0S, X1S[]={X0S}, X2S[][]={X1S}; static Object O0S, O1S[]={O0S}, O2S[][]={O1S}; - final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(1), LF1[]={LF0}, LF2[][]={LF1}; private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; transient Long LT0, LT1[]={LT0}, LT2[][]={LT1}; volatile Long LV0, LV1[]={LV0}, LV2[][]={LV1}; - static final Long LF0S = new Long(1), LF1S[]={LF0S}, LF2S[][]={LF1S}; + static final Long LF0S = Long.valueOf(1), LF1S[]={LF0S}, LF2S[][]={LF1S}; static private Long LP0S, LP1S[]={LP0S}, LP2S[][]={LP1S}; static public Long LU0S, LU1S[]={LU0S}, LU2S[][]={LU1S}; static protected Long LR0S, LR1S[]={LR0S}, LR2S[][]={LR1S}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003a.java index d9b4e38ab29..72b7e61c9fc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isStatic/isstatic003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ class isstatic003aClassToCheck extends isstatic003aSuperClass { static long[] cl = new long[10]; static { ci = 1; } - static { cL = new Long(1l); } + static { cL = Long.valueOf(1l); } static { for (int i = 0; i < 10; i++) { cl[i] = (long)i; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001a.java index c8abb6a319a..d65ae796b4e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/isSynthetic/issynthetic001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -79,7 +79,7 @@ class NestedClass { Class X0, X1[]={X0}, X2[][]={X1}; Object O0, O1[]={O0}, O2[][]={O1}; - final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(1), LF1[]={LF0}, LF2[][]={LF1}; private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001a.java index 70140884761..891a95dad1a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,7 +76,7 @@ interface Inter {} Class X0, X1[]={X0}, X2[][]={X1}; Object O0, O1[]={O0}, O2[][]={O1}; - final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(1), LF1[]={LF0}, LF2[][]={LF1}; private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003a.java index a4e96e9e6eb..686c158d065 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/name/name003a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ class name003aClassToCheck extends name003aSuperClass { static long[] cl = new long[10]; static { ci = 1; } - static { cL = new Long(1l); } + static { cL = Long.valueOf(1l); } static { for (int i = 0; i < 10; i++) { cl[i] = (long)i; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001a.java index 7202aa45494..be88795961c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/TypeComponent/signature/sign001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,7 +76,7 @@ interface Inter {} Class X0, X1[]={X0}, X2[][]={X1}; Object O0, O1[]={O0}, O2[][]={O1}; - final Long LF0 = new Long(1), LF1[]={LF0}, LF2[][]={LF1}; + final Long LF0 = Long.valueOf(1), LF1[]={LF0}, LF2[][]={LF1}; private Long LP0, LP1[]={LP0}, LP2[][]={LP1}; public Long LU0, LU1[]={LU0}, LU2[][]={LU1}; protected Long LR0, LR1[]={LR0}, LR2[][]={LR1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001a.java index ceaacf9e672..3077942260c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/_itself_/wevent001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -210,28 +210,28 @@ void run() { X0 = new Class(); X1 = new Class[] {X0}; X2 = new Class[][] {X1}; - Z0 = new Boolean(true); + Z0 = Boolean.valueOf(true); Z1 = new Boolean[] {Z0}; Z2 = new Boolean[][] {Z1}; - B0 = new Byte(java.lang.Byte.MIN_VALUE); + B0 = Byte.valueOf(java.lang.Byte.MIN_VALUE); B1 = new Byte[] {B0}; B2 = new Byte[][] {B1}; - C0 = new Character(java.lang.Character.MIN_VALUE); + C0 = Character.valueOf(java.lang.Character.MIN_VALUE); C1 = new Character[] {C0}; C2 = new Character[][]{C1}; - D0 = new Double(java.lang.Double.MIN_VALUE); + D0 = Double.valueOf(java.lang.Double.MIN_VALUE); D1 = new Double[] {D0}; D2 = new Double[][] {D1}; - F0 = new Float(java.lang.Float.MIN_VALUE); + F0 = Float.valueOf(java.lang.Float.MIN_VALUE); F1 = new Float[] {F0}; F2 = new Float[][] {F1}; - I0 = new Integer(java.lang.Integer.MIN_VALUE); + I0 = Integer.valueOf(java.lang.Integer.MIN_VALUE); I1 = new Integer[] {I0}; I2 = new Integer[][] {I1}; - L0 = new Long(java.lang.Long.MIN_VALUE); + L0 = Long.valueOf(java.lang.Long.MIN_VALUE); L1 = new Long[] {L0}; L2 = new Long[][] {L1}; - S0 = new Short(java.lang.Short.MIN_VALUE); + S0 = Short.valueOf(java.lang.Short.MIN_VALUE); S1 = new Short[] {S0}; S2 = new Short[][] {S1}; W0 = new String(); @@ -241,22 +241,22 @@ void run() { O1 = new Object[] {O0}; O2 = new Object[][] {O1}; - LS0 = new Long(java.lang.Long.MAX_VALUE); + LS0 = Long.valueOf(java.lang.Long.MAX_VALUE); LS1 = new Long[] {LS0}; LS2 = new Long[][] {LS1}; - LP0 = new Long(java.lang.Long.MAX_VALUE); + LP0 = Long.valueOf(java.lang.Long.MAX_VALUE); LP1 = new Long[] {LP0}; LP2 = new Long[][] {LP1}; - LU0 = new Long(java.lang.Long.MAX_VALUE); + LU0 = Long.valueOf(java.lang.Long.MAX_VALUE); LU1 = new Long[] {LU0}; LU2 = new Long[][] {LU1}; - LR0 = new Long(java.lang.Long.MAX_VALUE); + LR0 = Long.valueOf(java.lang.Long.MAX_VALUE); LR1 = new Long[] {LR0}; LR2 = new Long[][] {LR1}; - LT0 = new Long(java.lang.Long.MAX_VALUE); + LT0 = Long.valueOf(java.lang.Long.MAX_VALUE); LT1 = new Long[] {LT0}; LT2 = new Long[][] {LT1}; - LV0 = new Long(java.lang.Long.MAX_VALUE); + LV0 = Long.valueOf(java.lang.Long.MAX_VALUE); LV1 = new Long[] {LV0}; LV2 = new Long[][] {LV1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001a.java index 87dc289cbeb..2c38d9325eb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/object/object001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -172,28 +172,28 @@ void run() { X0 = new Class(); X1 = new Class[] {X0}; X2 = new Class[][] {X1}; - Z0 = new Boolean(true); + Z0 = Boolean.valueOf(true); Z1 = new Boolean[] {Z0}; Z2 = new Boolean[][] {Z1}; - B0 = new Byte(java.lang.Byte.MIN_VALUE); + B0 = Byte.valueOf(java.lang.Byte.MIN_VALUE); B1 = new Byte[] {B0}; B2 = new Byte[][] {B1}; - C0 = new Character(java.lang.Character.MIN_VALUE); + C0 = Character.valueOf(java.lang.Character.MIN_VALUE); C1 = new Character[] {C0}; C2 = new Character[][]{C1}; - D0 = new Double(java.lang.Double.MIN_VALUE); + D0 = Double.valueOf(java.lang.Double.MIN_VALUE); D1 = new Double[] {D0}; D2 = new Double[][] {D1}; - F0 = new Float(java.lang.Float.MIN_VALUE); + F0 = Float.valueOf(java.lang.Float.MIN_VALUE); F1 = new Float[] {F0}; F2 = new Float[][] {F1}; - I0 = new Integer(java.lang.Integer.MIN_VALUE); + I0 = Integer.valueOf(java.lang.Integer.MIN_VALUE); I1 = new Integer[] {I0}; I2 = new Integer[][] {I1}; - L0 = new Long(java.lang.Long.MIN_VALUE); + L0 = Long.valueOf(java.lang.Long.MIN_VALUE); L1 = new Long[] {L0}; L2 = new Long[][] {L1}; - S0 = new Short(java.lang.Short.MIN_VALUE); + S0 = Short.valueOf(java.lang.Short.MIN_VALUE); S1 = new Short[] {S0}; S2 = new Short[][] {S1}; W0 = new String(); @@ -203,22 +203,22 @@ void run() { O1 = new Object[] {O0}; O2 = new Object[][] {O1}; - LS0 = new Long(java.lang.Long.MAX_VALUE); + LS0 = Long.valueOf(java.lang.Long.MAX_VALUE); LS1 = new Long[] {LS0}; LS2 = new Long[][] {LS1}; - LP0 = new Long(java.lang.Long.MAX_VALUE); + LP0 = Long.valueOf(java.lang.Long.MAX_VALUE); LP1 = new Long[] {LP0}; LP2 = new Long[][] {LP1}; - LU0 = new Long(java.lang.Long.MAX_VALUE); + LU0 = Long.valueOf(java.lang.Long.MAX_VALUE); LU1 = new Long[] {LU0}; LU2 = new Long[][] {LU1}; - LR0 = new Long(java.lang.Long.MAX_VALUE); + LR0 = Long.valueOf(java.lang.Long.MAX_VALUE); LR1 = new Long[] {LR0}; LR2 = new Long[][] {LR1}; - LT0 = new Long(java.lang.Long.MAX_VALUE); + LT0 = Long.valueOf(java.lang.Long.MAX_VALUE); LT1 = new Long[] {LT0}; LT2 = new Long[][] {LT1}; - LV0 = new Long(java.lang.Long.MAX_VALUE); + LV0 = Long.valueOf(java.lang.Long.MAX_VALUE); LV1 = new Long[] {LV0}; LV2 = new Long[][] {LV1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001a.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001a.java index b9ae0a1ae3b..b3be677589e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/WatchpointEvent/valueCurrent/valuecur001a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -181,28 +181,28 @@ void run() { X0 = new Class(); X1 = new Class[] {X0}; X2 = new Class[][] {X1}; - Z0 = new Boolean(true); + Z0 = Boolean.valueOf(true); Z1 = new Boolean[] {Z0}; Z2 = new Boolean[][] {Z1}; - B0 = new Byte(java.lang.Byte.MIN_VALUE); + B0 = Byte.valueOf(java.lang.Byte.MIN_VALUE); B1 = new Byte[] {B0}; B2 = new Byte[][] {B1}; - C0 = new Character(java.lang.Character.MIN_VALUE); + C0 = Character.valueOf(java.lang.Character.MIN_VALUE); C1 = new Character[] {C0}; C2 = new Character[][]{C1}; - D0 = new Double(java.lang.Double.MIN_VALUE); + D0 = Double.valueOf(java.lang.Double.MIN_VALUE); D1 = new Double[] {D0}; D2 = new Double[][] {D1}; - F0 = new Float(java.lang.Float.MIN_VALUE); + F0 = Float.valueOf(java.lang.Float.MIN_VALUE); F1 = new Float[] {F0}; F2 = new Float[][] {F1}; - I0 = new Integer(java.lang.Integer.MIN_VALUE); + I0 = Integer.valueOf(java.lang.Integer.MIN_VALUE); I1 = new Integer[] {I0}; I2 = new Integer[][] {I1}; - L0 = new Long(java.lang.Long.MIN_VALUE); + L0 = Long.valueOf(java.lang.Long.MIN_VALUE); L1 = new Long[] {L0}; L2 = new Long[][] {L1}; - S0 = new Short(java.lang.Short.MIN_VALUE); + S0 = Short.valueOf(java.lang.Short.MIN_VALUE); S1 = new Short[] {S0}; S2 = new Short[][] {S1}; W0 = new String(); @@ -212,22 +212,22 @@ void run() { O1 = new Object[] {O0}; O2 = new Object[][] {O1}; - LS0 = new Long(java.lang.Long.MAX_VALUE); + LS0 = Long.valueOf(java.lang.Long.MAX_VALUE); LS1 = new Long[] {LS0}; LS2 = new Long[][] {LS1}; - LP0 = new Long(java.lang.Long.MAX_VALUE); + LP0 = Long.valueOf(java.lang.Long.MAX_VALUE); LP1 = new Long[] {LP0}; LP2 = new Long[][] {LP1}; - LU0 = new Long(java.lang.Long.MAX_VALUE); + LU0 = Long.valueOf(java.lang.Long.MAX_VALUE); LU1 = new Long[] {LU0}; LU2 = new Long[][] {LU1}; - LR0 = new Long(java.lang.Long.MAX_VALUE); + LR0 = Long.valueOf(java.lang.Long.MAX_VALUE); LR1 = new Long[] {LR0}; LR2 = new Long[][] {LR1}; - LT0 = new Long(java.lang.Long.MAX_VALUE); + LT0 = Long.valueOf(java.lang.Long.MAX_VALUE); LT1 = new Long[] {LT0}; LT2 = new Long[][] {LT1}; - LV0 = new Long(java.lang.Long.MAX_VALUE); + LV0 = Long.valueOf(java.lang.Long.MAX_VALUE); LV1 = new Long[] {LV0}; LV2 = new Long[][] {LV1}; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001.java index b7d458d28b1..117d66fe24c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ArrayReference/SetValues/setvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -264,7 +264,7 @@ void testCommand(long arrayID) { // add new int values for array components for (int i = ARRAY_FIRST_INDEX; i < ARRAY_FIRST_INDEX + ARRAY_ITEMS_COUNT; i++) { int intValue = i * 100 + 1; - JDWP.UntaggedValue value = new JDWP.UntaggedValue(new Integer(intValue)); + JDWP.UntaggedValue value = new JDWP.UntaggedValue(Integer.valueOf(intValue)); log.display(" untagged_value: " + value); command.addUntaggedValue(value, JDWP.Tag.INT); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001.java index 6ed567a5882..d9f5e31b653 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/InvokeMethod/invokemeth001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,7 +243,7 @@ void testCommand() { log.display(" arguments: " + ARGUMENTS_COUNT); command.addInt(ARGUMENTS_COUNT); for (int i = 0; i < ARGUMENTS_COUNT; i++) { - JDWP.Value value = new JDWP.Value(JDWP.Tag.INT, new Integer(ARGUMENT_VALUE)); + JDWP.Value value = new JDWP.Value(JDWP.Tag.INT, Integer.valueOf(ARGUMENT_VALUE)); log.display(" arg: " + value); command.addValue(value); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001.java index 16ffdb96059..ff23a6420e6 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ClassType/NewInstance/newinst001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -240,7 +240,7 @@ void testCommand() { log.display(" arguments: " + ARGUMENTS_COUNT); command.addInt(ARGUMENTS_COUNT); for (int i = 0; i < ARGUMENTS_COUNT; i++) { - JDWP.Value value = new JDWP.Value(JDWP.Tag.INT, new Integer(ARGUMENT_VALUE)); + JDWP.Value value = new JDWP.Value(JDWP.Tag.INT, Integer.valueOf(ARGUMENT_VALUE)); log.display(" arg: " + value); command.addValue(value); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001.java index 6f4fbff45b3..08668e91afa 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/GetValues/getvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,15 +69,15 @@ public class getvalues001 { // names and expected values of the tested fields static final Object fields [][] = { - { "booleanValue", "boolean", new Boolean(true), "own"}, - { "byteValue", "byte", new Byte((byte)0x0F), "own"}, - { "charValue", "char", new Character('Z'), "own"}, - { "intValue", "int", new Integer(100), "own"}, - { "shortValue", "short", new Short((short)10), "own"}, - { "longValue", "long", new Long((long)1000000), "own"}, - { "floatValue", "float", new Float((float)3.14), "own"}, - { "doubleValue", "double", new Double((double)2.8e-12), "own"}, - { "objectValue", "objectID", new Long((long)0), "own"}, + { "booleanValue", "boolean", Boolean.valueOf(true), "own"}, + { "byteValue", "byte", Byte.valueOf((byte)0x0F), "own"}, + { "charValue", "char", Character.valueOf('Z'), "own"}, + { "intValue", "int", Integer.valueOf(100), "own"}, + { "shortValue", "short", Short.valueOf((short)10), "own"}, + { "longValue", "long", Long.valueOf((long)1000000), "own"}, + { "floatValue", "float", Float.valueOf((float)3.14), "own"}, + { "doubleValue", "double", Double.valueOf((double)2.8e-12), "own"}, + { "objectValue", "objectID", Long.valueOf((long)0), "own"}, }; static final int FIELDS_COUNT = fields.length; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001.java index ad4698feec4..761a5bf19a4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ObjectReference/InvokeMethod/invokemeth001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -251,7 +251,7 @@ void testCommand() { log.display(" arguments: " + ARGUMENTS_COUNT); command.addInt(ARGUMENTS_COUNT); for (int i = 0; i < ARGUMENTS_COUNT; i++) { - JDWP.Value value = new JDWP.Value(JDWP.Tag.INT, new Integer(ARGUMENT_VALUE)); + JDWP.Value value = new JDWP.Value(JDWP.Tag.INT, Integer.valueOf(ARGUMENT_VALUE)); log.display(" arg: " + value); command.addValue(value); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001.java index 0d35a81873a..cafe1ba1d1a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/ReferenceType/GetValues/getvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,15 +66,15 @@ public class getvalues001 { // nested classes names and signatures array static final Object fields [][] = { - { "booleanValue", "boolean", new Boolean(true), "own"}, - { "byteValue", "byte", new Byte((byte)0x0F), "own"}, - { "charValue", "char", new Character('Z'), "own"}, - { "intValue", "int", new Integer(100), "own"}, - { "shortValue", "short", new Short((short)10), "own"}, - { "longValue", "long", new Long((long)1000000), "own"}, - { "floatValue", "float", new Float((float)3.14), "own"}, - { "doubleValue", "double", new Double((double)2.8e-12), "own"}, - { "objectValue", "objectID", new Long((long)0), "own"}, + { "booleanValue", "boolean", Boolean.valueOf(true), "own"}, + { "byteValue", "byte", Byte.valueOf((byte)0x0F), "own"}, + { "charValue", "char", Character.valueOf('Z'), "own"}, + { "intValue", "int", Integer.valueOf(100), "own"}, + { "shortValue", "short", Short.valueOf((short)10), "own"}, + { "longValue", "long", Long.valueOf((long)1000000), "own"}, + { "floatValue", "float", Float.valueOf((float)3.14), "own"}, + { "doubleValue", "double", Double.valueOf((double)2.8e-12), "own"}, + { "objectValue", "objectID", Long.valueOf((long)0), "own"}, }; static final int FIELDS_COUNT = fields.length; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001.java b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001.java index 63ce5229785..656ba90a250 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdwp/StackFrame/GetValues/getvalues001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,15 +73,15 @@ public class getvalues001 { // list of tested variables names and values static final Object variables[][] = { - { "booleanValue", "boolean", new Boolean(true), new Byte(JDWP.Tag.BOOLEAN)}, - { "byteValue", "byte", new Byte((byte)0x0F), new Byte(JDWP.Tag.BYTE) }, - { "charValue", "char", new Character('Z'), new Byte(JDWP.Tag.CHAR) }, - { "intValue", "int", new Integer(100), new Byte(JDWP.Tag.INT) }, - { "shortValue", "short", new Short((short)10), new Byte(JDWP.Tag.SHORT) }, - { "longValue", "long", new Long((long)1000000), new Byte(JDWP.Tag.LONG) }, - { "floatValue", "float", new Float((float)3.14), new Byte(JDWP.Tag.FLOAT) }, - { "doubleValue", "double", new Double((double)2.8e-12), new Byte(JDWP.Tag.DOUBLE) }, - { "objectValue", "objectID", new Long((long)0), new Byte(JDWP.Tag.OBJECT) } + { "booleanValue", "boolean", Boolean.valueOf(true), Byte.valueOf(JDWP.Tag.BOOLEAN)}, + { "byteValue", "byte", Byte.valueOf((byte)0x0F), Byte.valueOf(JDWP.Tag.BYTE) }, + { "charValue", "char", Character.valueOf('Z'), Byte.valueOf(JDWP.Tag.CHAR) }, + { "intValue", "int", Integer.valueOf(100), Byte.valueOf(JDWP.Tag.INT) }, + { "shortValue", "short", Short.valueOf((short)10), Byte.valueOf(JDWP.Tag.SHORT) }, + { "longValue", "long", Long.valueOf((long)1000000), Byte.valueOf(JDWP.Tag.LONG) }, + { "floatValue", "float", Float.valueOf((float)3.14), Byte.valueOf(JDWP.Tag.FLOAT) }, + { "doubleValue", "double", Double.valueOf((double)2.8e-12), Byte.valueOf(JDWP.Tag.DOUBLE) }, + { "objectValue", "objectID", Long.valueOf((long)0), Byte.valueOf(JDWP.Tag.OBJECT) } }; static final int VARIABLES_COUNT = variables.length; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach001/attach001TestRunner.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach001/attach001TestRunner.java index 125c7668cca..83433a10873 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach001/attach001TestRunner.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach001/attach001TestRunner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,7 +80,7 @@ public void run() { try { new TargetApplicationWaitingAgents().runTargetApplication(new String[] { "-" + AODTargetArgParser.agentsNumberParam, - new Integer(argParser.getAgents().size()).toString() }); + Integer.valueOf(argParser.getAgents().size()).toString() }); finishedSuccessfully = true; } catch (Throwable t) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetObjectMonitorUsage/objmonusage007.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetObjectMonitorUsage/objmonusage007.java index a4dad353c64..3fae11df418 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetObjectMonitorUsage/objmonusage007.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetObjectMonitorUsage/objmonusage007.java @@ -43,7 +43,7 @@ public class objmonusage007 { native static int getResult(); native static void check(Object o, Thread owner, int ec, int wc); - static inline class LocalValue { + static primitive class LocalValue { int i = 0; } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/PopFrame/popframe003p.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/PopFrame/popframe003p.java index 111bfbf4224..a04e11ce6c4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/PopFrame/popframe003p.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/PopFrame/popframe003p.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -220,7 +220,7 @@ void activeMeth(int i, long l, double d, char c, boolean b) { charGlFld = 'd'; booleanGlFld = false; strGlFld = "nstnc fld"; - objGl = new Integer(1973); + objGl = Integer.valueOf(1973); // for the global public instance fields bytePubGlFld = 7; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RedefineClasses/redefclass019/newclass_g/redefclass019a.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RedefineClasses/redefclass019/newclass_g/redefclass019a.java index a9d69e8cc2d..0d97b272fb0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RedefineClasses/redefclass019/newclass_g/redefclass019a.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/RedefineClasses/redefclass019/newclass_g/redefclass019a.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ public void chain3() { // dummy method to be breakpointed in agent void checkPoint() { - new Integer("4"); + Integer.valueOf("4"); return; } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/timers/JvmtiTest.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/timers/JvmtiTest.java index b98c6f5fe1b..ba5e3c7ab1b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/timers/JvmtiTest.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/unit/timers/JvmtiTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -123,7 +123,7 @@ public void run() { for (int i = iterations; i > 0; --i) { List list = new ArrayList(); for (int j = 10000; j > 0; --j) { - list.add(new Integer(j)); + list.add(Integer.valueOf(j)); } Collections.sort(list); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/MemoryUsage/from/from001.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/MemoryUsage/from/from001.java index 3822d8af156..3266c9ff98a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/MemoryUsage/from/from001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/MemoryUsage/from/from001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,7 @@ public static int run(String[] argv, PrintStream out) { Thread thread = Thread.currentThread(); long id = thread.getId(); - Object[] params = {new Long(id), new Integer(Integer.MAX_VALUE)}; + Object[] params = {Long.valueOf(id), Integer.valueOf(Integer.MAX_VALUE)}; String[] signature = {"long", "int"}; ObjectName mbeanObjectName = null; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/ThreadInfo/from_c/from_c001.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/ThreadInfo/from_c/from_c001.java index 55c35a8fb77..43a72152038 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/ThreadInfo/from_c/from_c001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/ThreadInfo/from_c/from_c001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,7 +88,7 @@ public static int run(String[] argv, PrintStream out) { Thread thread = Thread.currentThread(); long id = thread.getId(); - Object[] params = {new Long(id), new Integer(Integer.MAX_VALUE)}; + Object[] params = {Long.valueOf(id), Integer.valueOf(Integer.MAX_VALUE)}; String[] signature = {"long", "int"}; cdata = null; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/CustomMBeanServer.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/CustomMBeanServer.java index f02028c9cf0..68c4d52dd29 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/CustomMBeanServer.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/CustomMBeanServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -172,7 +172,7 @@ public ObjectInstance registerMBean(Object object, ObjectName name) try { newName = register.preRegister(this, name); } catch (Exception e) { - register.postRegister(new Boolean(false)); + register.postRegister(Boolean.valueOf(false)); throw new MBeanRegistrationException(e); } @@ -182,7 +182,7 @@ public ObjectInstance registerMBean(Object object, ObjectName name) log.trace(TRACE_ALL, "[registerMBean] " + newName); if (isRegistered(newName)) { - register.postRegister(new Boolean(false)); + register.postRegister(Boolean.valueOf(false)); throw new InstanceAlreadyExistsException("already registered"); } @@ -193,7 +193,7 @@ public ObjectInstance registerMBean(Object object, ObjectName name) throw new RuntimeOperationsException(e); } registeredMBeans.put(newName, new ObjectKeeper(instance, object)); - register.postRegister(new Boolean(true)); + register.postRegister(Boolean.valueOf(true)); return instance; } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/Monitor.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/Monitor.java index 5fef0a7fa7f..1636c7bb7da 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/Monitor.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/Monitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -423,7 +423,7 @@ protected MemoryUsage getMemoryUsageAttribute(ObjectName object, */ protected void setLongAttribute(ObjectName object, String name, long value) { - Attribute attribute = new Attribute(name, new Long(value)); + Attribute attribute = new Attribute(name, Long.valueOf(value)); try { getMBeanServer().setAttribute(object, attribute); @@ -442,7 +442,7 @@ protected void setLongAttribute(ObjectName object, String name, */ protected void setBooleanAttribute(ObjectName object, String name, boolean value) { - Attribute attribute = new Attribute(name, new Boolean(value)); + Attribute attribute = new Attribute(name, Boolean.valueOf(value)); try { getMBeanServer().setAttribute(object, attribute); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadMonitor.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadMonitor.java index b71d5199b97..0174f5b531c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadMonitor.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadMonitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -161,7 +161,7 @@ public ThreadInfo getThreadInfo(long id, int maxDepth) { return mbean.getThreadInfo(id, maxDepth); case SERVER_MODE: - Object[] params = {new Long(id), new Integer(maxDepth)}; + Object[] params = {Long.valueOf(id), Integer.valueOf(maxDepth)}; String[] signature = {"long", "int"}; try { @@ -311,7 +311,7 @@ public long getThreadCpuTime(long id) { return mbean.getThreadCpuTime(id); case SERVER_MODE: - Object[] params = {new Long(id)}; + Object[] params = {Long.valueOf(id)}; String[] signature = {"long"}; try { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMXBean.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMXBean.java index 323c385acd0..296fce522cb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMXBean.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/server/ServerMXBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,7 +101,7 @@ protected long getLongAttribute(String name) { * @return value of the attribute. */ protected void setLongAttribute(String name, long value) { - Attribute attribute = new Attribute(name, new Long(value)); + Attribute attribute = new Attribute(name, Long.valueOf(value)); try { mbeanServer.setAttribute(objectName, attribute); } catch (Exception e) { @@ -119,7 +119,7 @@ protected void setLongAttribute(String name, long value) { * @param value value of the attribute. */ protected void setBooleanAttribute(String name, boolean value) { - Attribute attribute = new Attribute(name, new Boolean(value)); + Attribute attribute = new Attribute(name, Boolean.valueOf(value)); try { mbeanServer.setAttribute(objectName, attribute); } catch (Exception e) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/cmon001.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/cmon001.java index d0e2da7fb08..52279b2946a 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/cmon001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/cmon001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,7 @@ public class cmon001 { private static volatile boolean testFailed = false; private static Integer calculated; + private static String calculatedSync = "abc"; private static Object common = new Object(); private static Object[] finishBarriers; private static long[] startTime; @@ -83,7 +84,7 @@ public static int run(String[] argv, PrintStream out) { for (int time = 0; time < ITERATIONS; time++) { log.display("Iteration: " + time); - calculated = new Integer(0); + calculated = Integer.valueOf(0); // Start all threads. Half of them are user threads, // others - daemon. @@ -203,8 +204,8 @@ public void run() { // Increase "calculated" value by one synchronized (common) { - synchronized (calculated) { - calculated = new Integer(calculated.intValue() + 1); + synchronized (calculatedSync) { + calculated = Integer.valueOf(calculated.intValue() + 1); } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace001.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace001.java index f8e4206e5ef..77b881ed0cf 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ public class strace001 { public static volatile boolean testFailed = false; public static Object common = new Object(); public static Integer activeThreads; + public static String activeThreadsSync = "abc"; private static Log log; private static int depth; private static int threadCount; @@ -69,7 +70,7 @@ public static int run(String[] argv, PrintStream out) { for (int i = 0; i < ITERATIONS; i++) { log.display("\nIteration: " + i); - activeThreads = new Integer(0); + activeThreads = Integer.valueOf(0); finish = false; // Start all threads. Half of them are user threads, @@ -292,9 +293,9 @@ public void run() { // This instance of the thread is alive synchronized (strace001.common) { - synchronized (strace001.activeThreads) { + synchronized (strace001.activeThreadsSync) { strace001.activeThreads - = new Integer(strace001.activeThreads.intValue() + 1); + = Integer.valueOf(strace001.activeThreads.intValue() + 1); } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/IORedirector.java b/test/hotspot/jtreg/vmTestbase/nsk/share/IORedirector.java index 31fbf1a231d..ea5076b24fa 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/IORedirector.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/IORedirector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,6 +53,7 @@ private IORedirector() { * * @see #IORedirector(BufferedReader,Log,String) */ + @Deprecated public IORedirector(InputStream in, OutputStream out) { this(); bin = new BufferedReader(new InputStreamReader(in)); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/Log.java b/test/hotspot/jtreg/vmTestbase/nsk/share/Log.java index 4a260fc3dd9..109c3ddd8f7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/Log.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Log.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,6 +75,7 @@ public class Log extends FinalizableObject { * * @deprecated Tests should not use this field directly. */ + @Deprecated protected PrintStream out = null; /** @@ -185,6 +186,7 @@ public static String getLevelsString() { * * @deprecated Extending test class with Log is obsolete. */ + @Deprecated protected Log() { // install finalizer to print errors summary at exit Finalizer finalizer = new Finalizer(this); @@ -311,6 +313,7 @@ public static String printExceptionToString(Object prefix, Throwable exception) * display() and complain() * are enough for testing purposes. */ + @Deprecated public synchronized void println(String message) { doPrint(message); if (!verbose() && isVerboseOnErrorEnabled()) { @@ -327,6 +330,7 @@ public synchronized void println(String message) { * display() and complain() * are enough for testing purposes. */ + @Deprecated public synchronized void comment(String message) { if (!verbose()) { doPrint(message); @@ -464,6 +468,7 @@ private void logExceptionForFailureAnalysis(String msg) { * * @deprecated This method is obsolete. */ + @Deprecated protected synchronized void logTo(PrintStream stream) { finalize(); // flush older log stream out = stream; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/TreeNodesDenotation.java b/test/hotspot/jtreg/vmTestbase/nsk/share/TreeNodesDenotation.java index 95d59c9dcc5..90ac5254af9 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/TreeNodesDenotation.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/TreeNodesDenotation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -113,7 +113,7 @@ public TreeNodesDenotation(String alphabeth) { int length = this.alphabeth.length(); Set pool = new HashSet(); // still empty for (int i=0; iBinder(ArgumentHandler,Log) * constructor. */ + @Deprecated public Binder (String args[]) { this(args, new Log(System.err)); } @@ -105,6 +106,7 @@ public Binder (String args[]) { * Binder(ArgumentHandler,Log) * constructor. */ + @Deprecated public Binder (String args[], Log log) { this(new ArgumentHandler(args), log); } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ValueConversionDebugger.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ValueConversionDebugger.java index 8e15c688b41..9bf75af8f07 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ValueConversionDebugger.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdi/ValueConversionDebugger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,25 +70,25 @@ public static boolean informationLoss(PrimitiveValue value, Class destType) { if (value instanceof ByteValue) { methodNameToCall += "ByteTo"; - param = new Byte(value.byteValue()); + param = Byte.valueOf(value.byteValue()); } else if (value instanceof ShortValue) { methodNameToCall += "ShortTo"; - param = new Short(value.shortValue()); + param = Short.valueOf(value.shortValue()); } else if (value instanceof CharValue) { methodNameToCall += "CharTo"; - param = new Character(value.charValue()); + param = Character.valueOf(value.charValue()); } else if (value instanceof IntegerValue) { methodNameToCall += "IntTo"; - param = new Integer(value.intValue()); + param = Integer.valueOf(value.intValue()); } else if (value instanceof LongValue) { methodNameToCall += "LongTo"; - param = new Long(value.longValue()); + param = Long.valueOf(value.longValue()); } else if (value instanceof FloatValue) { methodNameToCall += "FloatTo"; - param = new Float(value.floatValue()); + param = Float.valueOf(value.floatValue()); } else if (value instanceof DoubleValue) { methodNameToCall += "DoubleTo"; - param = new Double(value.doubleValue()); + param = Double.valueOf(value.doubleValue()); } else throw new IllegalArgumentException("Illegal PrimitiveValue: " + value); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Debugee.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Debugee.java index 6818364648d..ba1b4129cc7 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Debugee.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Debugee.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1442,7 +1442,7 @@ private void addSupertypes(long referenceTypeID, Vector supertypes, addSupertypes(typeID, supertypes, interfaces, superclasses, true, declared); } - Long value = new Long(typeID); + Long value = Long.valueOf(typeID); if (supertypes != null) { supertypes.add(value); } @@ -1477,7 +1477,7 @@ private void addSupertypes(long referenceTypeID, Vector supertypes, addSupertypes(typeID, supertypes, interfaces, superclasses, false, declared); } - Long value = new Long(typeID); + Long value = Long.valueOf(typeID); if (supertypes != null) { supertypes.add(value); } @@ -1536,13 +1536,13 @@ private void addFields(long referenceTypeID, Vector IDs, Vector na int modBits = reply.getInt(); if (IDs != null) - IDs.add(new Long(id)); + IDs.add(Long.valueOf(id)); if (names != null) names.add(name); if (signatures != null) signatures.add(signature); if (modifiers != null) - modifiers.add(new Integer(modBits)); + modifiers.add(Integer.valueOf(modBits)); } } catch (BoundException e) { @@ -1594,13 +1594,13 @@ private void addMethods(long referenceTypeID, Vector IDs, Vector n int modBits = reply.getInt(); if (IDs != null) - IDs.add(new Long(id)); + IDs.add(Long.valueOf(id)); if (names != null) names.add(name); if (signatures != null) signatures.add(signature); if (modifiers != null) - modifiers.add(new Integer(modBits)); + modifiers.add(Integer.valueOf(modBits)); } } catch (BoundException e) { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/JDWP.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/JDWP.java index a51fd829c25..c745eae93bb 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/JDWP.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/JDWP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -810,38 +810,38 @@ public void getValueFrom(Packet packet, byte tag) throws BoundException { switch (tag) { case JDWP.Tag.BYTE: { byte castedValue = packet.getByte(); - value = new Byte(castedValue); + value = Byte.valueOf(castedValue); } break; case JDWP.Tag.CHAR: { char castedValue = packet.getChar(); - value = new Character(castedValue); + value = Character.valueOf(castedValue); } break; case JDWP.Tag.FLOAT: { float castedValue = packet.getFloat(); - value = new Float(castedValue); + value = Float.valueOf(castedValue); } break; case JDWP.Tag.DOUBLE: { double castedValue = packet.getDouble(); - value = new Double(castedValue); + value = Double.valueOf(castedValue); } break; case JDWP.Tag.INT: { int castedValue = packet.getInt(); - value = new Integer(castedValue); + value = Integer.valueOf(castedValue); } break; case JDWP.Tag.SHORT: { short castedValue = packet.getShort(); - value = new Short(castedValue); + value = Short.valueOf(castedValue); } break; case JDWP.Tag.BOOLEAN: { byte castedValue = packet.getByte(); - value = new Boolean(castedValue != 0); + value = Boolean.valueOf(castedValue != 0); } break; case JDWP.Tag.LONG: { long castedValue = packet.getLong(); - value = new Long(castedValue); + value = Long.valueOf(castedValue); } break; case JDWP.Tag.VOID: { - value = new Long(0); + value = Long.valueOf(0); } break; case JDWP.Tag.ARRAY: case JDWP.Tag.OBJECT: @@ -851,7 +851,7 @@ public void getValueFrom(Packet packet, byte tag) throws BoundException { case JDWP.Tag.CLASS_LOADER: case JDWP.Tag.CLASS_OBJECT: { long castedValue = packet.getObjectID(); - value = new Long(castedValue); + value = Long.valueOf(castedValue); } break; default: { throw new Failure("Unknown tag found while reading value from packet: " + tag); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java index 48ac15e0096..d10f3281799 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -307,6 +307,7 @@ final public InputStream getStderr () { * * @deprecated Use redirectStdout(Log, String) instead. */ + @Deprecated public void redirectStdout(OutputStream out) { if (stdoutRedirector != null) { return; @@ -343,6 +344,7 @@ public void redirectStdout(Log log, String prefix) { * * @deprecated Use redirectStderr(Log, String) instead. */ + @Deprecated public void redirectStderr(OutputStream err) { if (stderrRedirector != null) { return; diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/ForceEarlyReturnTestThread.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/ForceEarlyReturnTestThread.java index e43c6801f0e..f0fedb95de3 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/ForceEarlyReturnTestThread.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/ForceEarlyReturnTestThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -451,14 +451,14 @@ private void logError(String message) public static ClassLoader expectedClassLoaderValue = new URLClassLoader(new URL[]{}); public static String expectedStringValue = "EXPECTED STRING"; public static Object expectedObjectValue = new Object(); - public static Boolean expectedBooleanWrapperValue = new Boolean(Boolean.TRUE); - public static Byte expectedByteWrapperValue = new Byte(Byte.MAX_VALUE); - public static Character expectedCharWrapperValue = new Character(Character.MAX_VALUE); - public static Short expectedShortWrapperValue = new Short(Short.MAX_VALUE); - public static Integer expectedIntWrapperValue = new Integer(Integer.MAX_VALUE); - public static Long expectedLongWrapperValue = new Long(Long.MAX_VALUE); - public static Float expectedFloatWrapperValue = new Float(Float.MAX_VALUE); - public static Double expectedDoubleWrapperValue = new Double(Double.MAX_VALUE); + public static Boolean expectedBooleanWrapperValue = Boolean.valueOf(Boolean.TRUE); + public static Byte expectedByteWrapperValue = Byte.valueOf(Byte.MAX_VALUE); + public static Character expectedCharWrapperValue = Character.valueOf(Character.MAX_VALUE); + public static Short expectedShortWrapperValue = Short.valueOf(Short.MAX_VALUE); + public static Integer expectedIntWrapperValue = Integer.valueOf(Integer.MAX_VALUE); + public static Long expectedLongWrapperValue = Long.valueOf(Long.MAX_VALUE); + public static Float expectedFloatWrapperValue = Float.valueOf(Float.MAX_VALUE); + public static Double expectedDoubleWrapperValue = Double.valueOf(Double.MAX_VALUE); // values which should be returned from test methods without forceEarlyReturn(): @@ -477,14 +477,14 @@ private void logError(String message) public static Class unexpectedClassObjectValue = Object.class; public static ClassLoader unexpectedClassLoaderValue = new URLClassLoader(new URL[]{}); public static Object unexpectedObjectValue = new Object(); - public static Boolean unexpectedBooleanWrapperValue = new Boolean(Boolean.FALSE); - public static Byte unexpectedByteWrapperValue = new Byte((byte)0); - public static Character unexpectedCharWrapperValue = new Character((char)0); - public static Short unexpectedShortWrapperValue = new Short((short)0); - public static Integer unexpectedIntWrapperValue = new Integer(0); - public static Long unexpectedLongWrapperValue = new Long(0); - public static Float unexpectedFloatWrapperValue = new Float(0); - public static Double unexpectedDoubleWrapperValue = new Double(0); + public static Boolean unexpectedBooleanWrapperValue = Boolean.valueOf(Boolean.FALSE); + public static Byte unexpectedByteWrapperValue = Byte.valueOf((byte)0); + public static Character unexpectedCharWrapperValue = Character.valueOf((char)0); + public static Short unexpectedShortWrapperValue = Short.valueOf((short)0); + public static Integer unexpectedIntWrapperValue = Integer.valueOf(0); + public static Long unexpectedLongWrapperValue = Long.valueOf(0); + public static Float unexpectedFloatWrapperValue = Float.valueOf(0); + public static Double unexpectedDoubleWrapperValue = Double.valueOf(0); public static int[] breakpointLines = { 49, @@ -534,13 +534,13 @@ private void logError(String message) public static Class invalidThreadGroupValue = ForceEarlyReturnTestThread.class; public static ClassLoader invalidClassObjectValue = new URLClassLoader(new URL[]{}); public static Object invalidClassLoaderValue = new Object(); - public static Byte invalidBooleanWrapperValue = new Byte(Byte.MAX_VALUE); - public static Short invalidByteWrapperValue = new Short(Short.MAX_VALUE); - public static Character invalidShortWrapperValue = new Character(Character.MAX_VALUE); - public static Integer invalidCharWrapperValue = new Integer(Integer.MAX_VALUE); - public static Long invalidIntWrapperValue = new Long(Long.MAX_VALUE); - public static Float invalidLongWrapperValue = new Float(Float.MAX_VALUE); - public static Double invalidFloatWrapperValue = new Double(Double.MAX_VALUE); + public static Byte invalidBooleanWrapperValue = Byte.valueOf(Byte.MAX_VALUE); + public static Short invalidByteWrapperValue = Short.valueOf(Short.MAX_VALUE); + public static Character invalidShortWrapperValue = Character.valueOf(Character.MAX_VALUE); + public static Integer invalidCharWrapperValue = Integer.valueOf(Integer.MAX_VALUE); + public static Long invalidIntWrapperValue = Long.valueOf(Long.MAX_VALUE); + public static Float invalidLongWrapperValue = Float.valueOf(Float.MAX_VALUE); + public static Double invalidFloatWrapperValue = Double.valueOf(Double.MAX_VALUE); public static Object[] invalidDoubleWrapperValue = new Object[1000]; // names of tested types, this names can be used to derive names of tested methods(typeName + 'Method'), diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/IOPipe.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/IOPipe.java index e6d242d9130..97bc8706ebf 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/IOPipe.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/IOPipe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,6 +51,7 @@ public class IOPipe extends SocketIOPipe { * * @see DebugeeArgumentHandler#createDebugeeIOPipe(Log) */ + @Deprecated public IOPipe(DebugeeArgumentHandler argumentHandler, Log log) { this(log, getTestHost(argumentHandler), argumentHandler.getPipePortNumber(), (long)argumentHandler.getWaitTime() * 60 * 1000, false); @@ -62,6 +63,7 @@ public IOPipe(DebugeeArgumentHandler argumentHandler, Log log) { * * @deprecated Use Debugee.createIOPipe() instead. */ + @Deprecated public IOPipe(DebugeeProcess debugee) { this(debugee.getLog(), debugee.getArgumentHandler().getDebugeeHost(), diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/NativeMethodsTestThread.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/NativeMethodsTestThread.java index c373e023bbf..965613a0935 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/NativeMethodsTestThread.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/NativeMethodsTestThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -116,21 +116,21 @@ private void log(String message) { public static Object expectedObjectValue = new Object(); - public static Boolean expectedBooleanWrapperValue = new Boolean(Boolean.TRUE); + public static Boolean expectedBooleanWrapperValue = Boolean.valueOf(Boolean.TRUE); - public static Byte expectedByteWrapperValue = new Byte(Byte.MAX_VALUE); + public static Byte expectedByteWrapperValue = Byte.valueOf(Byte.MAX_VALUE); - public static Character expectedCharWrapperValue = new Character(Character.MAX_VALUE); + public static Character expectedCharWrapperValue = Character.valueOf(Character.MAX_VALUE); - public static Short expectedShortWrapperValue = new Short(Short.MAX_VALUE); + public static Short expectedShortWrapperValue = Short.valueOf(Short.MAX_VALUE); - public static Integer expectedIntWrapperValue = new Integer(Integer.MAX_VALUE); + public static Integer expectedIntWrapperValue = Integer.valueOf(Integer.MAX_VALUE); - public static Long expectedLongWrapperValue = new Long(Long.MAX_VALUE); + public static Long expectedLongWrapperValue = Long.valueOf(Long.MAX_VALUE); - public static Float expectedFloatWrapperValue = new Float(Float.MAX_VALUE); + public static Float expectedFloatWrapperValue = Float.valueOf(Float.MAX_VALUE); - public static Double expectedDoubleWrapperValue = new Double(Double.MAX_VALUE); + public static Double expectedDoubleWrapperValue = Double.valueOf(Double.MAX_VALUE); // names of tested types, this names can be used to derive names of tested methods(typeName + 'Method'), public static String testedTypesNames[] = {"Void", "Boolean", "Byte", "Short", "Char", "Int", "Long", "Float", "Double", "ObjectArray", diff --git a/test/hotspot/jtreg/vmTestbase/nsk/stress/except/except004.java b/test/hotspot/jtreg/vmTestbase/nsk/stress/except/except004.java index c4898d16c74..865e506353c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/stress/except/except004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/stress/except/except004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -208,8 +208,8 @@ private static int runTests(PrintStream out, boolean exhaustHeap) { // Prepare some items, which will be used by the test: Object stringArray[] = new String[1]; - Object integerValue = new Integer(0); - Object doubleValue = new Double(0); + Object integerValue = Integer.valueOf(0); + Object doubleValue = Double.valueOf(0); Object trash = null; Field abraIntegerField; Field abraBooleanField; diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/RandomValueGen.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/RandomValueGen.java index 29bde65d780..ee90a0f81d2 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/RandomValueGen.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/RandomValueGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ public static Object nextDistinct(Class type, Object notEqualTo) throws Insta // A workaround for booleans. Sometimes RNG produces long series of trues or falses if ( type.equals(Boolean.class) || type.equals(boolean.class) ) - return new Boolean(! (Boolean) notEqualTo); + return Boolean.valueOf(! (Boolean) notEqualTo); throw new InstantiationException("Can't create distinct value for type=[" + type.getName() + "]; value=[" + notEqualTo + "]"); } diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/SimpleUnitTest.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/SimpleUnitTest.java index 02d9b10fa3e..660cd89d6b2 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/SimpleUnitTest.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/SimpleUnitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,7 +72,7 @@ public boolean run() throws Throwable { retArg = new Argument(SimpleUnitTest.class, sut); retArg.setPreserved(true); - Argument intArg = new Argument(int.class, new Integer(1)); + Argument intArg = new Argument(int.class, Integer.valueOf(1)); for ( ;; ) { try { @@ -86,7 +86,7 @@ public boolean run() throws Throwable { "test1", MethodType.methodType(SimpleUnitTest.class, int.class, float.class) ), - new Argument[] { new Argument(int.class, new Integer(1)), new Argument(float.class, new Float(1.0)) }, + new Argument[] { new Argument(int.class, Integer.valueOf(1)), new Argument(float.class, Float.valueOf(1.0)) }, true); break; @@ -99,7 +99,7 @@ public boolean run() throws Throwable { "test2", MethodType.methodType(SimpleUnitTest.class, int.class, float.class) ), - new Argument[] { new Argument(int.class, new Integer(1)), new Argument(float.class, new Float(1.0)) }, + new Argument[] { new Argument(int.class, Integer.valueOf(1)), new Argument(float.class, Float.valueOf(1.0)) }, true); break; diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/TestTypes.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/TestTypes.java index e04466c9f38..5903e9f21ea 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/TestTypes.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/share/TestTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -255,28 +255,28 @@ public static Object nextRandomValueForType(Class type) throws InstantiationE return null; if (type.equals(boolean.class) || type.equals(Boolean.class)) - return new Boolean(Env.getRNG().nextInt(2) == 0); + return Boolean.valueOf(Env.getRNG().nextInt(2) == 0); if (type.equals(byte.class) || type.equals(Byte.class)) - return new Byte((byte) Env.getRNG().nextInt(1 << Byte.SIZE)); + return Byte.valueOf((byte) Env.getRNG().nextInt(1 << Byte.SIZE)); if (type.equals(int.class) || type.equals(Integer.class)) - return new Integer(Env.getRNG().nextInt()); + return Integer.valueOf(Env.getRNG().nextInt()); if (type.equals(short.class) || type.equals(Short.class)) - return new Short((short) Env.getRNG().nextInt(1 << Short.SIZE)); + return Short.valueOf((short) Env.getRNG().nextInt(1 << Short.SIZE)); if (type.equals(long.class) || type.equals(Long.class)) - return new Long(Env.getRNG().nextLong()); + return Long.valueOf(Env.getRNG().nextLong()); if (type.equals(float.class) || type.equals(Float.class)) - return new Float(Env.getRNG().nextFloat()); + return Float.valueOf(Env.getRNG().nextFloat()); if (type.equals(double.class) || type.equals(Double.class)) - return new Double(Env.getRNG().nextDouble()); + return Double.valueOf(Env.getRNG().nextDouble()); if (type.equals(char.class) || type.equals(Character.class)) - return new Character((char) (32 + Env.getRNG().nextInt(96))); + return Character.valueOf((char) (32 + Env.getRNG().nextInt(96))); if (type.equals(Object.class)) return new Object(); diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java index bb4ef2b4697..d86a5890b4e 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/compiler/deoptimize/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,14 +91,14 @@ public class Test extends MultiThreadedTest { static class A { Object m() { - return new Integer(0); + return Integer.valueOf(0); } } static class B extends A { @Override Object m() { - return new Integer(1); + return Integer.valueOf(1); } } diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/compiler/i2c_c2i/Test.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/compiler/i2c_c2i/Test.java index 485a500b491..263bfe3900f 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/compiler/i2c_c2i/Test.java +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/meth/stress/compiler/i2c_c2i/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,7 +76,7 @@ public class Test extends MlvmTest { = Runtime.getRuntime().availableProcessors(); Object finalTarget() { - return new Integer(0); + return Integer.valueOf(0); } static class A { @@ -102,7 +102,7 @@ static class B extends A { Object m() throws Throwable { Env.traceNormal("Deoptimized m() in thread " + Thread.currentThread().getName()); - return new Integer(1); + return Integer.valueOf(1); } } @@ -122,7 +122,7 @@ public boolean run() throws Throwable { final MethodHandle mhB = MethodHandles.lookup().findVirtual(Test.class, "finalTarget", MethodType.methodType(Object.class)); - final Argument finalRetVal = Argument.fromValue(new Integer(0)); + final Argument finalRetVal = Argument.fromValue(Integer.valueOf(0)); finalRetVal.setPreserved(true); this.intermediateTarget = new A( diff --git a/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/shared/ClassFileGenerator.java b/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/shared/ClassFileGenerator.java index dd76b9a1c89..09e5e78abe7 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/shared/ClassFileGenerator.java +++ b/test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/shared/ClassFileGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -718,7 +718,7 @@ public void visitParamLong(LongParam l) { if (value == 0L) { mv.visitInsn(LCONST_0); } else { - mv.visitLdcInsn(new Long(value)); + mv.visitLdcInsn(Long.valueOf(value)); } } @@ -733,7 +733,7 @@ public void visitParamFloat(FloatParam f) { } else if (value == 2.0f) { mv.visitInsn(FCONST_2); } else { - mv.visitLdcInsn(new Float(value)); + mv.visitLdcInsn(Float.valueOf(value)); } } @@ -746,7 +746,7 @@ public void visitParamDouble(DoubleParam d) { } else if (value == 1.0d) { mv.visitInsn(DCONST_1); } else { - mv.visitLdcInsn(new Double(value)); + mv.visitLdcInsn(Double.valueOf(value)); } } diff --git a/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/PrettyPrintTest.java b/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/PrettyPrintTest.java index c3e1a68c059..1c356e74fd6 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/PrettyPrintTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/common/prettyprint/PrettyPrintTest.java @@ -66,7 +66,7 @@ /* * @test - * @bug 6439439 8087303 8174025 8223291 8249867 + * @bug 6439439 8087303 8174025 8223291 8249867 8261209 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @run testng/othervm -DrunSecMngr=true common.prettyprint.PrettyPrintTest * @run testng/othervm common.prettyprint.PrettyPrintTest @@ -78,11 +78,15 @@ public class PrettyPrintTest { private static final String JDK_IS_STANDALONE = "http://www.oracle.com/xml/jaxp/properties/isStandalone"; private static final String SP_JDK_IS_STANDALONE = "jdk.xml.isStandalone"; + // pretty-print=true, isStandalone=true, linebreak added after header private static final String XML_LB = "\n\n"; - private static final String XML_NOLB + // pretty-print=true, isStandalone=false, no linebreak after header + private static final String XML_PPTRUE_NOLB = "\n"; - + // pretty-print=false, isStandalone=true, linebreak added after header + private static final String XML_PPFALSE_LB + = "\n"; /* * test CDATA, elements only, text and element, xml:space property, mixed * node types. @@ -101,16 +105,22 @@ public Object[][] xmlData() throws Exception { /* * Bug: 8249867 * DataProvider: for testing the isStandalone property - * Data columns: property, system property, value, expected result + * Data columns: pretty-print, property, system property, value, expected result */ @DataProvider(name = "setting") Object[][] getData() throws Exception { return new Object[][]{ - {false, true, true, XML_LB}, //set System property - {false, true, false, XML_NOLB},//set System property - {true, false, true, XML_LB}, //set property - {true, false, false, XML_NOLB},//set property - {false, false, false, XML_NOLB} //default + // pretty-print = true + {true, false, true, true, XML_LB}, //set System property = true + {true, false, true, false, XML_PPTRUE_NOLB}, //set System property = false + {true, true, false, true, XML_LB}, //set property = true + {true, true, false, false, XML_PPTRUE_NOLB}, //set property = false + {true, false, false, false, XML_PPTRUE_NOLB},//default + + // pretty-print = false + {false, false, true, true, XML_PPFALSE_LB}, //System property = true + {false, true, false, true, XML_PPFALSE_LB}, //set property = true + }; } @@ -134,9 +144,14 @@ Object[][] getSystemProperty() throws Exception { * Bug: 8249867 * Verifies the use of the new property "isStandalone" and the * corresponding System property "jdk.xml.isStandalone". + * + * Bug: 8261209 + * Verifies that the property takes effect regardless of the settings of + * property "pretty-print". */ @Test(dataProvider = "setting") - public void test(boolean p, boolean sp, boolean val, String expected) + public void testIsStandalone_DOMLS(boolean pretty, boolean p, boolean sp, + boolean val, String expected) throws Exception { if (sp) { setSystemProperty(SP_JDK_IS_STANDALONE, Boolean.toString(val)); @@ -144,9 +159,12 @@ public void test(boolean p, boolean sp, boolean val, String expected) Document document = getDocument(); DOMImplementationLS impl = (DOMImplementationLS)document.getImplementation(); LSSerializer ser = impl.createLSSerializer(); - ser.getDomConfig().setParameter("format-pretty-print", true); + DOMConfiguration config = ser.getDomConfig(); + if (pretty) { + config.setParameter("format-pretty-print", true); + } if (p && !sp) { - ser.getDomConfig().setParameter(JDK_IS_STANDALONE, val); + config.setParameter(JDK_IS_STANDALONE, val); } if (sp) { clearSystemProperty(SP_JDK_IS_STANDALONE); diff --git a/test/jdk/ProblemList-Xcomp.txt b/test/jdk/ProblemList-Xcomp.txt index 6f1f7f36b74..77b61348af5 100644 --- a/test/jdk/ProblemList-Xcomp.txt +++ b/test/jdk/ProblemList-Xcomp.txt @@ -29,4 +29,3 @@ java/lang/invoke/MethodHandles/CatchExceptionTest.java 8146623 generic-all java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTest.java 8256368 generic-all -jdk/incubator/vector/VectorHash.java 8259430 generic-all diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 95a89dbe497..43f9747f9ce 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -821,6 +821,8 @@ javax/rmi/ssl/SSLSocketParametersTest.sh 8162906 generic- javax/script/Test7.java 8239361 generic-all +jdk/dynalink/TypeConverterFactoryMemoryLeakTest.java 8261483 generic-all + ############################################################################ # jdk_jfr @@ -828,7 +830,6 @@ javax/script/Test7.java 8239361 generic- jdk/jfr/event/runtime/TestNetworkUtilizationEvent.java 8228990,8229370 generic-all jdk/jfr/event/compiler/TestCodeSweeper.java 8225209 generic-all jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows-all -jdk/jfr/jmx/streaming/TestRotate.java 8257215 generic-all jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64 jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 diff --git a/test/jdk/com/sun/crypto/provider/KeyAgreement/SupportedDHParamGens.java b/test/jdk/com/sun/crypto/provider/KeyAgreement/SupportedDHParamGens.java index ac3f384bcf2..27f010dd141 100644 --- a/test/jdk/com/sun/crypto/provider/KeyAgreement/SupportedDHParamGens.java +++ b/test/jdk/com/sun/crypto/provider/KeyAgreement/SupportedDHParamGens.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,14 +23,16 @@ /** * @test - * @bug 8072452 + * @bug 8072452 8163498 * @summary Support DHE sizes up to 8192-bits and DSA sizes up to 3072-bits + * This test has been split based on lower/higher key sizes in order to + * reduce individual execution times and run in parallel + * (see SupportedDHParamGensLongKey.java) * @run main/timeout=300 SupportedDHParamGens 512 * @run main/timeout=300 SupportedDHParamGens 768 * @run main/timeout=300 SupportedDHParamGens 832 * @run main/timeout=300 SupportedDHParamGens 1024 * @run main/timeout=600 SupportedDHParamGens 2048 - * @run main/timeout=700 SupportedDHParamGens 3072 */ import java.math.BigInteger; diff --git a/test/jdk/com/sun/crypto/provider/KeyAgreement/SupportedDHParamGensLongKey.java b/test/jdk/com/sun/crypto/provider/KeyAgreement/SupportedDHParamGensLongKey.java new file mode 100644 index 00000000000..740486e06cf --- /dev/null +++ b/test/jdk/com/sun/crypto/provider/KeyAgreement/SupportedDHParamGensLongKey.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8072452 8163498 + * @summary Support DHE sizes up to 8192-bits and DSA sizes up to 3072-bits + * This test has been split based on lower/higher key sizes in order to + * reduce individual execution times and run in parallel + * (see SupportedDHParamGens.java) + * @run main/timeout=700 SupportedDHParamGens 3072 + */ diff --git a/test/jdk/com/sun/jdi/JdbInlineTypesTest.java b/test/jdk/com/sun/jdi/JdbInlineTypesTest.java index 85a46ce91d6..2afc8dd9a40 100644 --- a/test/jdk/com/sun/jdi/JdbInlineTypesTest.java +++ b/test/jdk/com/sun/jdi/JdbInlineTypesTest.java @@ -39,8 +39,8 @@ class JdbInlineTypesTestTarg { static MyValue static_v = new MyValue(16,'s', (byte)3, (byte)(byte)9); - - static inline class SmallValue { + + static primitive class SmallValue { byte b0,b1; public SmallValue(byte b0, byte b1) { @@ -48,8 +48,8 @@ public SmallValue(byte b0, byte b1) { this.b1 = b1; } } - - static inline class MyValue { + + static primitive class MyValue { int a; char b; SmallValue small; @@ -65,16 +65,16 @@ public static class ObjectContainer { int i; MyValue value; } - + public static void bkpt() { - MyValue v = new MyValue(12,'c', (byte)5, (byte)(byte)7); + MyValue v = new MyValue(12,'c', (byte)5, (byte)(byte)7); Object b = new Object(); b = v; - Object o = new Object(); + Object o = new Object(); MyValue v2 = new MyValue(12,'c', (byte)5, (byte)7); MyValue v3 = new MyValue(11,'c', (byte)5, (byte)7); ObjectContainer oc = new ObjectContainer(); - MyValue[] array = new MyValue[10]; + MyValue[] array = new MyValue[10]; System.out.println("v == v " + (b == b)); int i = 0; //@1 breakpoint } @@ -100,62 +100,62 @@ protected void runCases() { setBreakpointsFromTestSource("JdbInlineTypesTest.java", 1); // Run to breakpoint #1 execCommand(JdbCommand.run()) - .shouldContain("Breakpoint hit"); + .shouldContain("Breakpoint hit"); + + // Printing a local variable containing an instance of an inline type + execCommand(JdbCommand.print("v")) + .shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=12 b=c small=[JdbInlineTypesTestTarg$SmallValue b0=5 b1=7]]\""); - // Printing a local variable containing an instance of an inline type - execCommand(JdbCommand.print("v")) - .shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=12 b=c small=[JdbInlineTypesTestTarg$SmallValue b0=5 b1=7]]\""); + // Printing an instance of an inline type stored in a local variable of type Object + execCommand(JdbCommand.print("b")) + .shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=12 b=c small=[JdbInlineTypesTestTarg$SmallValue b0=5 b1=7]]\""); - // Printing an instance of an inline type stored in a local variable of type Object - execCommand(JdbCommand.print("b")) - .shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=12 b=c small=[JdbInlineTypesTestTarg$SmallValue b0=5 b1=7]]\""); + // Trying to set a local variable containing an instance of an inline types to null + execCommand(JdbCommand.set("v", "null")).shouldContain("Can't set an inline type to null"); - // Trying to set a local variable containing an instance of an inline types to null - execCommand(JdbCommand.set("v", "null")).shouldContain("Can't set an inline type to null"); + // Storing an instance of an inline type into a local variable of type Object + execCommand(JdbCommand.set("o", "v")).shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=12 b=c small=[JdbInlineTypesTestTarg$SmallValue b0=5 b1=7]]\""); - // Storing an instance of an inline type into a local variable of type Object - execCommand(JdbCommand.set("o", "v")).shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=12 b=c small=[JdbInlineTypesTestTarg$SmallValue b0=5 b1=7]]\""); + // Printing a field of an instance of an inline type + execCommand(JdbCommand.print("v.a")).shouldContain(" = 12"); - // Printing a field of an instance of an inline type - execCommand(JdbCommand.print("v.a")).shouldContain(" = 12"); + // Print a flattened field of an instance of an inline type + execCommand(JdbCommand.print("v.small")).shouldContain(" = \"[JdbInlineTypesTestTarg$SmallValue b0=5 b1=7]\""); - // Print a flattened field of an instance of an inline type - execCommand(JdbCommand.print("v.small")).shouldContain(" = \"[JdbInlineTypesTestTarg$SmallValue b0=5 b1=7]\""); + // Print a flattened field of an instance of an identity class + // Note field b has a not printible value (character 0); + execCommand(JdbCommand.print("oc.value")).shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=0 b=\u0000 small=[JdbInlineTypesTestTarg$SmallValue b0=0 b1=0]]\""); - // Print a flattened field of an instance of an identity class - // Note field b has a not printible value (character 0); - execCommand(JdbCommand.print("oc.value")).shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=0 b=\u0000 small=[JdbInlineTypesTestTarg$SmallValue b0=0 b1=0]]\""); + // Updating a flattened field of an instance of an identity class + execCommand(JdbCommand.set("oc.value", "v")).shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=12 b=c small=[JdbInlineTypesTestTarg$SmallValue b0=5 b1=7]]\""); - // Updating a flattened field of an instance of an identity class - execCommand(JdbCommand.set("oc.value", "v")).shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=12 b=c small=[JdbInlineTypesTestTarg$SmallValue b0=5 b1=7]]\""); + // Trying set a flattened field to null + execCommand(JdbCommand.set("oc.value", "null")).shouldContain("Can't set an inline type to null"); - // Trying set a flattened field to null - execCommand(JdbCommand.set("oc.value", "null")).shouldContain("Can't set an inline type to null"); + // Print a static inline field + execCommand(JdbCommand.print("JdbInlineTypesTestTarg.static_v")) + .shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=16 b=s small=[JdbInlineTypesTestTarg$SmallValue b0=3 b1=9]]\""); - // Print a static inline field - execCommand(JdbCommand.print("JdbInlineTypesTestTarg.static_v")) - .shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=16 b=s small=[JdbInlineTypesTestTarg$SmallValue b0=3 b1=9]]\""); + // Updating a static inline field + execCommand(JdbCommand.set("JdbInlineTypesTestTarg.static_v", "v")).shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=12 b=c small=[JdbInlineTypesTestTarg$SmallValue b0=5 b1=7]]\""); - // Updating a static inline field - execCommand(JdbCommand.set("JdbInlineTypesTestTarg.static_v", "v")).shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=12 b=c small=[JdbInlineTypesTestTarg$SmallValue b0=5 b1=7]]\""); + // Trying set a inline field to null + execCommand(JdbCommand.set("JdbInlineTypesTestTarg.static_v", "null")).shouldContain("Can't set an inline type to null"); - // Trying set a inline field to null - execCommand(JdbCommand.set("JdbInlineTypesTestTarg.static_v", "null")).shouldContain("Can't set an inline type to null"); - - // Printing an element of an inline type array - execCommand(JdbCommand.print("array[0]")).shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=0 b=\u0000 small=[JdbInlineTypesTestTarg$SmallValue b0=0 b1=0]]\""); + // Printing an element of an inline type array + execCommand(JdbCommand.print("array[0]")).shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=0 b=\u0000 small=[JdbInlineTypesTestTarg$SmallValue b0=0 b1=0]]\""); - // Setting an element of an inline type array - execCommand(JdbCommand.set("array[0]", "v")).shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=12 b=c small=[JdbInlineTypesTestTarg$SmallValue b0=5 b1=7]]\""); + // Setting an element of an inline type array + execCommand(JdbCommand.set("array[0]", "v")).shouldContain(" = \"[JdbInlineTypesTestTarg$MyValue a=12 b=c small=[JdbInlineTypesTestTarg$SmallValue b0=5 b1=7]]\""); - // Trying to set an element of an inline type array to null - execCommand(JdbCommand.set("array[1]", "null")).shouldContain("Can't set an inline type to null"); + // Trying to set an element of an inline type array to null + execCommand(JdbCommand.set("array[1]", "null")).shouldContain("Can't set an inline type to null"); - // Testing substitutability test - execCommand(JdbCommand.print("v == v2")).shouldContain(" = true"); - execCommand(JdbCommand.print("v == v3")).shouldContain(" = false"); + // Testing substitutability test + execCommand(JdbCommand.print("v == v2")).shouldContain(" = true"); + execCommand(JdbCommand.print("v == v3")).shouldContain(" = false"); - // Testing inline type instance creation - execCommand(JdbCommand.print("new JdbInlineTypesTestTarg$SmallValue(42,64)")).shouldContain(" = \"[JdbInlineTypesTestTarg$SmallValue b0=42 b1=64]\""); + // Testing inline type instance creation + execCommand(JdbCommand.print("new JdbInlineTypesTestTarg$SmallValue(42,64)")).shouldContain(" = \"[JdbInlineTypesTestTarg$SmallValue b0=42 b1=64]\""); } } diff --git a/test/jdk/com/sun/jdi/JdbOptions.java b/test/jdk/com/sun/jdi/JdbOptions.java index b6fb965e319..114aa3ddd50 100644 --- a/test/jdk/com/sun/jdi/JdbOptions.java +++ b/test/jdk/com/sun/jdi/JdbOptions.java @@ -34,9 +34,17 @@ import lib.jdb.JdbCommand; import jdk.test.lib.process.OutputAnalyzer; +import java.io.IOException; +import java.io.PrintStream; import java.lang.management.ManagementFactory; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Arrays; import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; class JbdOptionsTarg { static final String OK_MSG = "JbdOptionsTarg: OK"; @@ -49,47 +57,62 @@ static String propString(String name, String value) { return "prop[" + name + "] = >" + value + "<"; } - public static void main(String[] args) { - System.out.println(OK_MSG); - // print all args - List vmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments(); - for (String s: vmArgs) { - System.out.println(argString(s)); - } - // print requested sys.props - for (String p: args) { - System.out.println(propString(p, System.getProperty(p))); + /** + * 1st argument is a filename to redirect application output, + * the rest are names of the properties to dump. + */ + public static void main(String[] args) throws IOException { + String outFile = args[0]; + try (PrintStream out = new PrintStream(outFile, StandardCharsets.UTF_8)) { + out.println(OK_MSG); + // print all args + List vmArgs = ManagementFactory.getRuntimeMXBean().getInputArguments(); + for (String s : vmArgs) { + out.println(argString(s)); + } + // print requested sys.props (skip 1st arg which is output filename) + for (int i=1; i < args.length; i++) { + String p = args[i]; + out.println(propString(p, System.getProperty(p))); + } } } } public class JdbOptions { + private static final String outFilename = UUID.randomUUID().toString() + ".out"; + private static final Path outPath = Paths.get(outFilename); private static final String targ = JbdOptionsTarg.class.getName(); public static void main(String[] args) throws Exception { // the simplest case test("-connect", - "com.sun.jdi.CommandLineLaunch:vmexec=java,options=-client -XX:+PrintVMOptions,main=" + targ) + "com.sun.jdi.CommandLineLaunch:vmexec=java,options=-client -XX:+PrintVMOptions" + + ",main=" + targ + " " + outFilename) .expectedArg("-XX:+PrintVMOptions"); // pass property through 'options' test("-connect", - "com.sun.jdi.CommandLineLaunch:vmexec=java,options='-Dboo=foo',main=" + targ + " boo") + "com.sun.jdi.CommandLineLaunch:vmexec=java,options='-Dboo=foo'" + + ",main=" + targ + " " + outFilename + " boo") .expectedProp("boo", "foo"); // property with spaces test("-connect", - "com.sun.jdi.CommandLineLaunch:vmexec=java,options=\"-Dboo=foo 2\",main=" + targ + " boo") + "com.sun.jdi.CommandLineLaunch:vmexec=java,options=\"-Dboo=foo 2\"" + + ",main=" + targ + " " + outFilename + " boo") .expectedProp("boo", "foo 2"); // property with spaces (with single quotes) test("-connect", - "com.sun.jdi.CommandLineLaunch:vmexec=java,options='-Dboo=foo 2',main=" + targ + " boo") + "com.sun.jdi.CommandLineLaunch:vmexec=java,options='-Dboo=foo 2'" + + ",main=" + targ + " " + outFilename + " boo") .expectedProp("boo", "foo 2"); // properties with spaces (with single quotes) test("-connect", - "com.sun.jdi.CommandLineLaunch:vmexec=java,options=-Dboo=foo '-Dboo2=foo 2',main=" + targ + " boo boo2") + "com.sun.jdi.CommandLineLaunch:vmexec=java,options=-Dboo=foo '-Dboo2=foo 2'" + + ",main=" + targ + " " + outFilename + " boo boo2") .expectedProp("boo", "foo") .expectedProp("boo2", "foo 2"); @@ -98,7 +121,7 @@ public static void main(String[] args) throws Exception { "com.sun.jdi.CommandLineLaunch:vmexec=java,options=\"-client\" \"-XX:+PrintVMOptions\"" + " -XX:+IgnoreUnrecognizedVMOptions" + " \"-XX:StartFlightRecording=dumponexit=true,maxsize=500M\" \"-XX:FlightRecorderOptions=repository=jfrrep\"" - + ",main=" + targ) + + ",main=" + targ + " " + outFilename) .expectedArg("-XX:StartFlightRecording=dumponexit=true,maxsize=500M") .expectedArg("-XX:FlightRecorderOptions=repository=jfrrep"); @@ -107,7 +130,7 @@ public static void main(String[] args) throws Exception { "com.sun.jdi.CommandLineLaunch:vmexec=java,options='-client' '-XX:+PrintVMOptions'" + " -XX:+IgnoreUnrecognizedVMOptions" + " '-XX:StartFlightRecording=dumponexit=true,maxsize=500M' '-XX:FlightRecorderOptions=repository=jfrrep'" - + ",main=" + targ) + + ",main=" + targ + " " + outFilename) .expectedArg("-XX:StartFlightRecording=dumponexit=true,maxsize=500M") .expectedArg("-XX:FlightRecorderOptions=repository=jfrrep"); @@ -120,7 +143,7 @@ public static void main(String[] args) throws Exception { + " -XX:+IgnoreUnrecognizedVMOptions" + " \"-XX:StartFlightRecording=dumponexit=true,maxsize=500M\"" + " '-XX:FlightRecorderOptions=repository=jfrrep'" - + ",main=" + targ + " prop1 prop2 prop3 prop4") + + ",main=" + targ + " " + outFilename + " prop1 prop2 prop3 prop4") .expectedProp("prop1", "val1") .expectedProp("prop2", "val 2") .expectedProp("prop3", "val3") @@ -154,12 +177,18 @@ private static TestResult test(String... args) throws Exception { .map(s -> s.replace("\"", "\\\"")) .toArray(String[]::new); } + try (Jdb jdb = new Jdb(args)) { jdb.waitForSimplePrompt(1024, true); // 1024 lines should be enough jdb.command(JdbCommand.run().allowExit()); - OutputAnalyzer out = new OutputAnalyzer(jdb.getJdbOutput()); - out.shouldContain(JbdOptionsTarg.OK_MSG); - return new TestResult(out); } + String output = Files.readAllLines(outPath, StandardCharsets.UTF_8).stream() + .collect(Collectors.joining(System.getProperty("line.separator"))); + Files.deleteIfExists(outPath); + System.out.println("Debuggee output: ["); + System.out.println(output); + System.out.println("]"); + OutputAnalyzer out = new OutputAnalyzer(output); + return new TestResult(out); } } diff --git a/test/jdk/java/awt/BasicStroke/TestNullShape.java b/test/jdk/java/awt/BasicStroke/TestNullShape.java new file mode 100644 index 00000000000..219282d137f --- /dev/null +++ b/test/jdk/java/awt/BasicStroke/TestNullShape.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/** + * @test + * @bug 6211257 + * @summary Verifies NPE is thrown for BasicStroke.createStrokedShape(null). + */ +import java.awt.BasicStroke; +import java.awt.Shape; + +public class TestNullShape { + + public static void main(String[] args) { + + BasicStroke bs = new BasicStroke(); + try { + Shape s = bs.createStrokedShape(null); + System.out.println("result: false"); + throw new RuntimeException("NPE is expected"); + } catch (NullPointerException ne) { + System.out.println("result (npe): true"); + } + } +} diff --git a/test/jdk/java/awt/Graphics/TestNullSetColor.java b/test/jdk/java/awt/Graphics/TestNullSetColor.java new file mode 100644 index 00000000000..57183218d65 --- /dev/null +++ b/test/jdk/java/awt/Graphics/TestNullSetColor.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +import java.awt.Graphics; +import java.awt.Color; +import java.awt.image.BufferedImage; + +/** + * @test + * @bug 6436374 + * @summary Verifies that passing null to setColor() will be ignored. + */ +public class TestNullSetColor { + + public static void main(String[] argv) { + BufferedImage bi = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB); + Graphics g = bi.getGraphics(); + + g.setColor(Color.RED); + g.setColor(null); + + if (g.getColor() != Color.RED) { + throw new RuntimeException("Setting setColor(null) is not ignored"); + } + } +} diff --git a/test/jdk/java/awt/Window/MainKeyWindowTest/libTestMainKeyWindow.m b/test/jdk/java/awt/Window/MainKeyWindowTest/libTestMainKeyWindow.m index ea585a79514..11f329757a7 100644 --- a/test/jdk/java/awt/Window/MainKeyWindowTest/libTestMainKeyWindow.m +++ b/test/jdk/java/awt/Window/MainKeyWindowTest/libTestMainKeyWindow.m @@ -24,11 +24,45 @@ */ #import -#import +#import static NSWindow *testWindow; static NSColorPanel *colorPanel; +#define JNI_COCOA_ENTER(env) \ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; \ + @try { + +#define JNI_COCOA_EXIT(env) \ + } \ + @catch (NSException *e) { \ + NSLog(@"%@", [e callStackSymbols]); \ + } \ + @finally { \ + [pool drain]; \ + }; + +/* + * Pass the block to a selector of a class that extends NSObject + * There is no need to copy the block since this class always waits. + */ +@interface BlockRunner : NSObject { } + ++ (void)invokeBlock:(void (^)())block; +@end + +@implementation BlockRunner + ++ (void)invokeBlock:(void (^)())block{ + block(); +} + ++ (void)performBlock:(void (^)())block { + [self performSelectorOnMainThread:@selector(invokeBlock:) withObject:block waitUntilDone:YES]; +} + +@end + /* * Class: TestMainKeyWindow * Method: setup @@ -36,7 +70,7 @@ */ JNIEXPORT void JNICALL Java_TestMainKeyWindow_setup(JNIEnv *env, jclass cl) { - JNF_COCOA_ENTER(env); + JNI_COCOA_ENTER(env); void (^block)() = ^(){ NSScreen *mainScreen = [[NSScreen screens] objectAtIndex:0]; @@ -68,10 +102,10 @@ JNIEXPORT void JNICALL Java_TestMainKeyWindow_setup(JNIEnv *env, jclass cl) if ([NSThread isMainThread]) { block(); } else { - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:block]; + [BlockRunner performBlock:block]; } - JNF_COCOA_EXIT(env); + JNI_COCOA_EXIT(env); } /* @@ -81,7 +115,7 @@ JNIEXPORT void JNICALL Java_TestMainKeyWindow_setup(JNIEnv *env, jclass cl) */ JNIEXPORT void JNICALL Java_TestMainKeyWindow_takedown(JNIEnv *env, jclass cl) { - JNF_COCOA_ENTER(env); + JNI_COCOA_ENTER(env); void (^block)() = ^(){ if (testWindow != nil) { @@ -97,10 +131,10 @@ JNIEXPORT void JNICALL Java_TestMainKeyWindow_takedown(JNIEnv *env, jclass cl) if ([NSThread isMainThread]) { block(); } else { - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:block]; + [BlockRunner performBlock:block]; } - JNF_COCOA_EXIT(env); + JNI_COCOA_EXIT(env); } /* @@ -111,13 +145,13 @@ JNIEXPORT void JNICALL Java_TestMainKeyWindow_takedown(JNIEnv *env, jclass cl) JNIEXPORT void JNICALL Java_TestMainKeyWindow_activateApplication (JNIEnv *env, jclass cl) { - JNF_COCOA_ENTER(env); + JNI_COCOA_ENTER(env); void (^block)() = ^(){ [NSApp activateIgnoringOtherApps:YES]; }; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:block]; + [BlockRunner performBlock:block]; - JNF_COCOA_EXIT(env); + JNI_COCOA_EXIT(env); } diff --git a/test/jdk/java/awt/color/BuiltInDataVariation.java b/test/jdk/java/awt/color/BuiltInDataVariation.java new file mode 100644 index 00000000000..16528ee2600 --- /dev/null +++ b/test/jdk/java/awt/color/BuiltInDataVariation.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_ColorSpace; +import java.awt.color.ICC_Profile; +import java.util.Arrays; +import java.util.Set; + +import static java.awt.color.ColorSpace.*; + +/** + * @test + * @bug 8261282 + * @summary Checks that all built-in profiles and data are different. + */ +public final class BuiltInDataVariation { + + public static void main(String[] args) { + testColorProfiles(); + testColorSpaces(); + } + + private static void testColorProfiles() { + ICC_Profile srgb = ICC_Profile.getInstance(CS_sRGB); + ICC_Profile lrgb = ICC_Profile.getInstance(CS_LINEAR_RGB); + ICC_Profile xyz = ICC_Profile.getInstance(CS_CIEXYZ); + ICC_Profile pycc = ICC_Profile.getInstance(CS_PYCC); + ICC_Profile gray = ICC_Profile.getInstance(CS_GRAY); + + test(srgb, lrgb, xyz, pycc, gray); + test(Arrays.hashCode(srgb.getData()), Arrays.hashCode(lrgb.getData()), + Arrays.hashCode(xyz.getData()), Arrays.hashCode(pycc.getData()), + Arrays.hashCode(gray.getData())); + } + + private static void testColorSpaces() { + var srgb = (ICC_ColorSpace) ColorSpace.getInstance(CS_sRGB); + var lrgb = (ICC_ColorSpace) ColorSpace.getInstance(CS_LINEAR_RGB); + var xyz = (ICC_ColorSpace) ColorSpace.getInstance(CS_CIEXYZ); + var pycc = (ICC_ColorSpace) ColorSpace.getInstance(CS_PYCC); + var gray = (ICC_ColorSpace) ColorSpace.getInstance(CS_GRAY); + + test(srgb, lrgb, xyz, pycc, gray); + test(srgb.getProfile(), lrgb.getProfile(), xyz.getProfile(), + pycc.getProfile(), gray.getProfile()); + test(Arrays.hashCode(srgb.getProfile().getData()), + Arrays.hashCode(lrgb.getProfile().getData()), + Arrays.hashCode(xyz.getProfile().getData()), + Arrays.hashCode(pycc.getProfile().getData()), + Arrays.hashCode(gray.getProfile().getData())); + } + + private static void test(Object srgb, Object lrgb, Object xyz, + Object pycc, Object gray) { + Set.of(srgb, lrgb, xyz, pycc, gray); + } +} diff --git a/test/jdk/java/awt/color/GetInstanceBrokenData.java b/test/jdk/java/awt/color/GetInstanceBrokenData.java new file mode 100644 index 00000000000..1ba78177b33 --- /dev/null +++ b/test/jdk/java/awt/color/GetInstanceBrokenData.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.color.ICC_Profile; + +/** + * @test + * @bug 6211198 + * @summary IllegalArgumentException in ICC_Profile.getInstance for broken data + */ +public final class GetInstanceBrokenData { + + public static void main(String[] argv) { + byte b[] = {-21, -22, -23}; + try { + ICC_Profile p = ICC_Profile.getInstance(b); + throw new RuntimeException("IllegalArgumentException is expected"); + } catch (IllegalArgumentException ignored) { + // expected + } + } +} diff --git a/test/jdk/java/awt/color/GetInstanceNullData.java b/test/jdk/java/awt/color/GetInstanceNullData.java index 9543455477a..b31e3cc4d3d 100644 --- a/test/jdk/java/awt/color/GetInstanceNullData.java +++ b/test/jdk/java/awt/color/GetInstanceNullData.java @@ -27,7 +27,7 @@ /** * @test - * @bug 4176618 7042594 + * @bug 4176618 7042594 6211198 * @summary This interactive test verifies that passing null to * ICC_ProfileRGB.getInstance() does not crash the VM. * An IllegalArgumentException: Invalid ICC Profile Data should be diff --git a/test/jdk/java/awt/color/HotStaticLocks.java b/test/jdk/java/awt/color/HotStaticLocks.java new file mode 100644 index 00000000000..95762b6da20 --- /dev/null +++ b/test/jdk/java/awt/color/HotStaticLocks.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; + +import static java.awt.color.ColorSpace.CS_CIEXYZ; +import static java.awt.color.ColorSpace.CS_GRAY; +import static java.awt.color.ColorSpace.CS_LINEAR_RGB; +import static java.awt.color.ColorSpace.CS_PYCC; +import static java.awt.color.ColorSpace.CS_sRGB; + +/** + * @test + * @bug 8261282 + * @summary Checks static locks in the ColorSpace/ICC_Profile classes. + */ +public final class HotStaticLocks { + + public static void main(String[] args) throws Exception { + testICCProfile(); + testColorSpace(); + } + + private static void testICCProfile() throws Exception { + int[] spaces = {CS_sRGB, CS_LINEAR_RGB, CS_CIEXYZ, CS_PYCC, CS_GRAY}; + for (int cs : spaces) { + synchronized (ICC_Profile.class) { + Thread t = new Thread(() -> ICC_Profile.getInstance(cs)); + t.start(); + t.join(); + } + } + } + + private static void testColorSpace() throws Exception { + int[] spaces = {CS_sRGB, CS_LINEAR_RGB, CS_CIEXYZ, CS_PYCC, CS_GRAY}; + for (int cs : spaces) { + synchronized (ColorSpace.class) { + Thread t = new Thread(() -> ColorSpace.getInstance(cs)); + t.start(); + t.join(); + } + } + } +} diff --git a/test/jdk/java/awt/color/ICC_Profile/GetInstanceBrokenStream.java b/test/jdk/java/awt/color/ICC_Profile/GetInstanceBrokenStream.java new file mode 100644 index 00000000000..b98cae0cdca --- /dev/null +++ b/test/jdk/java/awt/color/ICC_Profile/GetInstanceBrokenStream.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.ICC_Profile; +import java.io.ByteArrayInputStream; +import java.io.IOException; + +/** + * @test + * @bug 8261107 + * @summary Short and broken streams should be reported as unsupported + */ +public final class GetInstanceBrokenStream { + + public static void main(String[] args) throws IOException { + // Empty header + testHeader(new byte[]{}); + // Short header + testHeader(new byte[]{-12, 3, 45}); + // Broken header + testHeader(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 0x61, 0x63, 0x73, 0x70}); + } + + private static void testHeader(byte[] data) throws IOException { + ByteArrayInputStream bais = new ByteArrayInputStream(data); + try { + ICC_Profile.getInstance(bais); + } catch (IllegalArgumentException e) { + // expected + } + } +} diff --git a/test/jdk/java/awt/color/ICC_Profile/WriteProfileToFile.java b/test/jdk/java/awt/color/ICC_Profile/WriteProfileToFile.java new file mode 100644 index 00000000000..0ea4b3b0835 --- /dev/null +++ b/test/jdk/java/awt/color/ICC_Profile/WriteProfileToFile.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.nio.file.Files; +import java.util.Arrays; + +/** + * @test + * @bug 8261200 + * @summary Checks that we can write/read the icc profile to/from file + */ +public final class WriteProfileToFile { + + public static void main(String[] args) throws Exception { + byte[] gold = ICC_Profile.getInstance(ColorSpace.CS_sRGB).getData(); + + testViaDataArray(gold); + testViaFile(gold); + testViaStream(gold); + } + + private static void testViaDataArray(byte[] gold) { + ICC_Profile profile = ICC_Profile.getInstance(gold); + compare(gold, profile.getData()); + } + + private static void testViaFile(byte[] gold) throws Exception { + ICC_Profile profile = ICC_Profile.getInstance(gold); + profile.write("fileName.icc"); + try { + profile = ICC_Profile.getInstance("fileName.icc"); + compare(gold, profile.getData()); + } finally { + Files.delete(new File("fileName.icc").toPath()); + } + } + + private static void testViaStream(byte[] gold) throws Exception { + ICC_Profile profile = ICC_Profile.getInstance(gold); + File file = new File("fileName.icc"); + try (OutputStream outputStream = new FileOutputStream(file)) { + profile.write(outputStream); + profile = ICC_Profile.getInstance("fileName.icc"); + compare(gold, profile.getData()); + } finally { + Files.delete(file.toPath()); + } + } + + private static void compare(byte[] data1, byte[] data2) { + if (!Arrays.equals(data1, data2)) { + throw new RuntimeException("Data mismatch"); + } + } +} diff --git a/test/jdk/java/awt/image/TestNullAASF.java b/test/jdk/java/awt/image/TestNullAASF.java new file mode 100644 index 00000000000..c93b799ca00 --- /dev/null +++ b/test/jdk/java/awt/image/TestNullAASF.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/** + * @test + * @bug 6211242 + * @summary Verifies IAE is thrown if 0 is passed to + * AreaAveragingScaleFilter(width,height) constructor. + */ +import java.awt.image.AreaAveragingScaleFilter; + +public class TestNullAASF { + public static void main(String[] args) { + AreaAveragingScaleFilter filter = null; + try { + filter = new AreaAveragingScaleFilter(0, Integer.MAX_VALUE); + System.out.println("result: false"); + throw new RuntimeException("IAE expected for width=0"); + } catch (IllegalArgumentException e) { + System.out.println("result (iae): true"); + } + try { + filter = new AreaAveragingScaleFilter(Integer.MAX_VALUE, 0); + System.out.println("result: false"); + throw new RuntimeException("IAE expected for height=0"); + } catch (IllegalArgumentException e) { + System.out.println("result (iae): true"); + } + } +} diff --git a/test/jdk/java/io/Serializable/serialFilter/GlobalFilterTest.java b/test/jdk/java/io/Serializable/serialFilter/GlobalFilterTest.java index 1e679242890..6ebf35726d0 100644 --- a/test/jdk/java/io/Serializable/serialFilter/GlobalFilterTest.java +++ b/test/jdk/java/io/Serializable/serialFilter/GlobalFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,6 +53,18 @@ * * @summary Test Global Filters */ + +/* @test + * @bug 8261160 + * @summary Add a deserialization JFR event + * @build GlobalFilterTest SerialFilterTest + * @requires vm.hasJFR + * @run testng/othervm/policy=security.policy + * -XX:StartFlightRecording=name=DeserializationEvent,dumponexit=true + * -Djava.security.properties=${test.src}/java.security-extra1 + * -Djava.security.debug=properties GlobalFilterTest + */ + @Test public class GlobalFilterTest { private static final String serialPropName = "jdk.serialFilter"; diff --git a/test/jdk/java/lang/Math/ExpCornerCaseTests.java b/test/jdk/java/lang/Math/ExpCornerCaseTests.java index c7948b19af8..16168254378 100644 --- a/test/jdk/java/lang/Math/ExpCornerCaseTests.java +++ b/test/jdk/java/lang/Math/ExpCornerCaseTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011,2020, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8255368 + * @bug 8255368 8240632 * @summary Tests corner cases of Math.exp */ @@ -46,6 +46,10 @@ private static int testExpCornerCases() { double [][] testCases = { {+0x4.0p8, Double.POSITIVE_INFINITY}, {+0x2.71p12, Double.POSITIVE_INFINITY}, + + // Identified special cases in IEEE 754 exp operation + {+0.0, 1.0}, + {-0.0, 1.0}, }; for (double[] testCase : testCases) { diff --git a/test/jdk/java/lang/Math/HypotTests.java b/test/jdk/java/lang/Math/HypotTests.java index 0f31a8881f8..d7e562ca5fd 100644 --- a/test/jdk/java/lang/Math/HypotTests.java +++ b/test/jdk/java/lang/Math/HypotTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @library /test/lib * @build jdk.test.lib.RandomFactory * @run main HypotTests - * @bug 4851638 4939441 8078672 + * @bug 4851638 4939441 8078672 8240632 * @summary Tests for {Math, StrictMath}.hypot (use -Dseed=X to set PRNG seed) * @author Joseph D. Darcy * @key randomness @@ -198,6 +198,13 @@ static int testHypot() { return failures; } + /** + * Verify +0.0 is returned if both arguments are zero. + */ + private static int testHypotZeros() { + return testHypotCase(0.0, 0.0, +0.0, 0.0); + } + static int testHypotCase(double input1, double input2, double expected) { return testHypotCase(input1,input2, expected, 1); } @@ -237,6 +244,7 @@ public static void main(String argv[]) { int failures = 0; failures += testHypot(); + failures += testHypotZeros(); if (failures > 0) { System.err.println("Testing the hypot incurred " diff --git a/test/jdk/java/lang/Math/Ieee754SpecialCaseTests.java b/test/jdk/java/lang/Math/Ieee754SpecialCaseTests.java new file mode 100644 index 00000000000..d8192f2fee3 --- /dev/null +++ b/test/jdk/java/lang/Math/Ieee754SpecialCaseTests.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8240632 + * @summary Test special cases of IEEE 754 recommended ops not otherwise tested + * @build Tests + * @build Ieee754SpecialCaseTests + * @run main Ieee754SpecialCaseTests + */ + +public class Ieee754SpecialCaseTests { + private Ieee754SpecialCaseTests() {throw new AssertionError("No instances for you.");} + + public static void main(String... args) { + int failures = 0; + + failures += testSpecialCos(); + failures += testSpecialAcos(); + failures += testSpecialAtan(); + failures += testSpecialLog(); + + if (failures > 0) { + System.err.printf("Testing special cases incurred %d failures.%n", failures); + throw new RuntimeException(); + } + } + private static int testSpecialCos() { + int failures = 0; + double [][] testCases = { + {+0.0, 1.0}, + {-0.0, 1.0}, + }; + + for(double[] testCase: testCases) { + failures += testCosCase(testCase[0], testCase[1]); + } + + return failures; + } + + private static int testCosCase(double input, double expected) { + int failures = 0; + failures += Tests.test("Math.cos", input, Math.cos(input), expected); + failures += Tests.test("StrictMath.cos", input, StrictMath.cos(input), expected); + return failures; + } + + private static int testSpecialAcos() { + int failures = 0; + double [][] testCases = { + {1.0, 0.0}, + }; + + for(double[] testCase: testCases) { + failures += testAcosCase(testCase[0], testCase[1]); + } + + return failures; + } + + private static int testAcosCase(double input, double expected) { + int failures = 0; + failures += Tests.test("Math.acos", input, Math.acos(input), expected); + failures += Tests.test("StrictMath.acos", input, StrictMath.acos(input), expected); + return failures; + } + + private static int testSpecialAtan() { + int failures = 0; + double [][] testCases = { + {Double.POSITIVE_INFINITY, +Math.PI/2.0}, + {Double.NEGATIVE_INFINITY, -Math.PI/2.0}, + }; + + for(double[] testCase: testCases) { + failures += testAtanCase(testCase[0], testCase[1]); + } + + return failures; + } + + private static int testAtanCase(double input, double expected) { + int failures = 0; + failures += Tests.test("Math.atan", input, Math.atan(input), expected); + failures += Tests.test("StrictMath.atan", input, StrictMath.atan(input), expected); + return failures; + } + + private static int testSpecialLog() { + int failures = 0; + double [][] testCases = { + {1.0, +0.0}, + }; + + for(double[] testCase: testCases) { + failures += testLogCase(testCase[0], testCase[1]); + } + + return failures; + } + + private static int testLogCase(double input, double expected) { + int failures = 0; + failures += Tests.test("Math.log", input, Math.log(input), expected); + failures += Tests.test("StrictMath.log", input, StrictMath.log(input), expected); + return failures; + } +} diff --git a/test/jdk/java/lang/ProcessBuilder/InheritIO/InheritIO.sh b/test/jdk/java/lang/ProcessBuilder/InheritIO/InheritIO.sh deleted file mode 100644 index a8cfa51f3dd..00000000000 --- a/test/jdk/java/lang/ProcessBuilder/InheritIO/InheritIO.sh +++ /dev/null @@ -1,84 +0,0 @@ -# -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please 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 8023130 -# @summary (process) ProcessBuilder#inheritIO does not work on Windows -# @run shell InheritIO.sh - -if [ "x${TESTSRC}" = "x" ]; then - echo "TESTSRC not set. Test cannot execute. Failed." - exit 1 -fi - -if [ "x${TESTJAVA}" = "x" ]; then - echo "TESTJAVA not set. Test cannot execute. Failed." - exit 1 -fi - -if [ "x${COMPILEJAVA}" = "x" ]; then - COMPILEJAVA="${TESTJAVA}" -fi - -JAVA="${TESTJAVA}/bin/java" -JAVAC="${COMPILEJAVA}/bin/javac" - -cp -f ${TESTSRC}/InheritIO.java . - -# compile the class ourselves, so this can run as a standalone test - -${JAVAC} InheritIO.java -RES="$?" -if [ ${RES} != 0 ]; then - echo 'FAIL: Cannot compile InheritIO.java' - exit ${RES} -fi - - -for TEST_NAME in TestInheritIO TestRedirectInherit -do - ${JAVA} ${TESTVMOPTS} -classpath . \ - 'InheritIO$'${TEST_NAME} printf message > stdout.txt 2> stderr.txt - - RES="$?" - if [ ${RES} != 0 ]; then - echo 'FAIL: InheritIO$'${TEST_NAME}' failed with '${RES} - exit ${RES} - fi - - OUT_EXPECTED='message' - OUT_RECEIVED=`cat stdout.txt` - if [ "x${OUT_RECEIVED}" != "x${OUT_EXPECTED}" ]; then - echo "FAIL: unexpected '${OUT_RECEIVED}' in stdout" - exit 1 - fi - - ERR_EXPECTED='exit value: 0' - ERR_RECEIVED=`cat stderr.txt` - if [ "x${ERR_RECEIVED}" != "x${ERR_EXPECTED}" ]; then - echo "FAIL: unexpected '${ERR_RECEIVED}' in stderr" - exit 1 - fi -done - -echo 'PASS: InheritIO works as expected' diff --git a/test/jdk/java/lang/ProcessBuilder/InheritIOTest.java b/test/jdk/java/lang/ProcessBuilder/InheritIOTest.java new file mode 100644 index 00000000000..340507cb37b --- /dev/null +++ b/test/jdk/java/lang/ProcessBuilder/InheritIOTest.java @@ -0,0 +1,84 @@ +/* + * 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 8023130 8166026 + * @summary Unit test for java.lang.ProcessBuilder inheritance of standard output and standard error streams + * @library /test/lib + * @build jdk.test.lib.process.* + * @run testng InheritIOTest + */ + +import java.util.List; +import static java.lang.ProcessBuilder.Redirect.INHERIT; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +public class InheritIOTest { + + private static final String EXIT_VALUE_TEMPLATE = "exit value: %d"; + private static final String EXPECTED_RESULT_STDOUT = "message"; + private static final String EXPECTED_RESULT_STDERR = EXIT_VALUE_TEMPLATE.formatted(0); + + @DataProvider + public Object[][] testCases() { + return new Object[][]{ + new Object[] { List.of("InheritIOTest$TestInheritIO", "printf", EXPECTED_RESULT_STDOUT) }, + new Object[] { List.of("InheritIOTest$TestRedirectInherit", "printf", EXPECTED_RESULT_STDOUT) } + }; + } + + @Test(dataProvider = "testCases") + public void testInheritWithoutRedirect(List arguments) throws Throwable { + ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(arguments); + OutputAnalyzer outputAnalyzer = ProcessTools.executeCommand(processBuilder); + outputAnalyzer.shouldHaveExitValue(0); + assertEquals(outputAnalyzer.getStdout(), EXPECTED_RESULT_STDOUT); + assertEquals(outputAnalyzer.getStderr(), EXPECTED_RESULT_STDERR); + } + + public static class TestInheritIO { + public static void main(String args[]) throws Throwable { + int err = new ProcessBuilder(args).inheritIO().start().waitFor(); + System.err.printf(EXIT_VALUE_TEMPLATE, err); + System.exit(err); + } + } + + public static class TestRedirectInherit { + public static void main(String args[]) throws Throwable { + int err = new ProcessBuilder(args) + .redirectInput(INHERIT) + .redirectOutput(INHERIT) + .redirectError(INHERIT) + .start().waitFor(); + System.err.printf(EXIT_VALUE_TEMPLATE, err); + System.exit(err); + } + } + +} diff --git a/test/jdk/java/lang/StringBuilder/HugeCapacity.java b/test/jdk/java/lang/StringBuilder/HugeCapacity.java index 7da3e368e23..9f1617a9dd2 100644 --- a/test/jdk/java/lang/StringBuilder/HugeCapacity.java +++ b/test/jdk/java/lang/StringBuilder/HugeCapacity.java @@ -27,14 +27,20 @@ * @summary Capacity should not get close to Integer.MAX_VALUE unless * necessary * @requires (sun.arch.data.model == "64" & os.maxMemory >= 6G) - * @run main/othervm -Xms5G -Xmx5G HugeCapacity + * @run main/othervm -Xms5G -Xmx5G -XX:+CompactStrings HugeCapacity true + * @run main/othervm -Xms5G -Xmx5G -XX:-CompactStrings HugeCapacity false */ public class HugeCapacity { private static int failures = 0; public static void main(String[] args) { - testLatin1(); + if (args.length == 0) { + throw new IllegalArgumentException("Need the argument"); + } + boolean isCompact = Boolean.parseBoolean(args[0]); + + testLatin1(isCompact); testUtf16(); testHugeInitialString(); testHugeInitialCharSequence(); @@ -43,11 +49,12 @@ public static void main(String[] args) { } } - private static void testLatin1() { + private static void testLatin1(boolean isCompact) { try { + int divisor = isCompact ? 2 : 4; StringBuilder sb = new StringBuilder(); - sb.ensureCapacity(Integer.MAX_VALUE / 2); - sb.ensureCapacity(Integer.MAX_VALUE / 2 + 1); + sb.ensureCapacity(Integer.MAX_VALUE / divisor); + sb.ensureCapacity(Integer.MAX_VALUE / divisor + 1); } catch (OutOfMemoryError oom) { oom.printStackTrace(); failures++; diff --git a/test/jdk/java/lang/StringBuilder/Insert.java b/test/jdk/java/lang/StringBuilder/Insert.java index d4b1ef28d86..ad1c7df20e2 100644 --- a/test/jdk/java/lang/StringBuilder/Insert.java +++ b/test/jdk/java/lang/StringBuilder/Insert.java @@ -27,9 +27,10 @@ /** * @test - * @run testng Insert * @bug 4914802 8257511 * @summary Test StringBuilder.insert sanity tests + * @run testng/othervm -XX:-CompactStrings Insert + * @run testng/othervm -XX:+CompactStrings Insert */ @Test public class Insert { diff --git a/test/jdk/java/lang/System/OsVersionTest.java b/test/jdk/java/lang/System/OsVersionTest.java index 977b7ca314d..356fbccc224 100644 --- a/test/jdk/java/lang/System/OsVersionTest.java +++ b/test/jdk/java/lang/System/OsVersionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 SAP SE. All rights reserved. + * Copyright (c) 2015, 2021, SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ import jdk.test.lib.Platform; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import jtreg.SkippedException; /* * @test @@ -49,8 +50,14 @@ public static void main(String args[]) throws Throwable { } else if (Platform.isOSX()) { OutputAnalyzer output = ProcessTools.executeProcess("sw_vers", "-productVersion"); - if (!osVersion.equals(output.getOutput().trim())) { - throw new Error(osVersion + " != " + output.getOutput().trim()); + String swVersOutput = output.getOutput().trim(); + if (!osVersion.equals(swVersOutput)) { + // This section can be removed if minimum build SDK is xcode 12+ + if (swVersOutput.startsWith(osVersion)) { + throw new SkippedException("MacOS version only matches in parts, this is expected when " + + "JDK was built with Xcode < 12 and MacOS version patch is > 0"); + } + throw new Error(osVersion + " != " + swVersOutput); } } else if (Platform.isAix()) { diff --git a/test/jdk/java/lang/invoke/VarHandles/Point.java b/test/jdk/java/lang/invoke/VarHandles/Point.java index 88357aad881..0e3b75b19ed 100644 --- a/test/jdk/java/lang/invoke/VarHandles/Point.java +++ b/test/jdk/java/lang/invoke/VarHandles/Point.java @@ -21,7 +21,7 @@ * questions. */ -public inline class Point { +public primitive class Point { public static Point getInstance(int x, int y) { return new Point(x, y); diff --git a/test/jdk/java/lang/invoke/VarHandles/Value.java b/test/jdk/java/lang/invoke/VarHandles/Value.java index f873ffc9ae7..776a55fb1a6 100644 --- a/test/jdk/java/lang/invoke/VarHandles/Value.java +++ b/test/jdk/java/lang/invoke/VarHandles/Value.java @@ -21,7 +21,7 @@ * questions. */ -final inline class Value { +final primitive class Value { final char char_v; final byte byte_v; final boolean boolean_v; diff --git a/test/jdk/java/net/DatagramSocket/DatagramSocketExample.java b/test/jdk/java/net/DatagramSocket/DatagramSocketExample.java new file mode 100644 index 00000000000..2609380a5dd --- /dev/null +++ b/test/jdk/java/net/DatagramSocket/DatagramSocketExample.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8237352 + * @summary Verifies that the examples using DatagramSocket for + * sending and receiving multicast datagrams are functional. + * See "Multicasting with DatagramSocket" API note in + * DatagramSocket.java + * + * @library /test/lib + * @build jdk.test.lib.NetworkConfiguration + * jdk.test.lib.net.IPSupport + * @run main/othervm DatagramSocketExample + * @run main/othervm -Djava.net.preferIPv4Stack=true DatagramSocketExample + * @run main/othervm -Djdk.usePlainDatagramSocketImpl=true DatagramSocketExample + * @run main/othervm -Djdk.usePlainDatagramSocketImpl=true -Djava.net.preferIPv4Stack=true DatagramSocketExample + */ + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.ProtocolFamily; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.SocketOption; +import java.net.SocketTimeoutException; +import java.net.StandardSocketOptions; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import jdk.test.lib.NetworkConfiguration; +import jdk.test.lib.net.IPSupport; + +import static java.net.StandardProtocolFamily.INET; +import static java.net.StandardProtocolFamily.INET6; +import static java.net.StandardSocketOptions.IP_MULTICAST_IF; +import static java.net.StandardSocketOptions.IP_MULTICAST_LOOP; +import static java.net.StandardSocketOptions.IP_MULTICAST_TTL; +import static java.net.StandardSocketOptions.SO_REUSEADDR; + +public class DatagramSocketExample { + static final ProtocolFamily UNSPEC = () -> "UNSPEC"; + + public static void main(String[] args) throws IOException { + IPSupport.throwSkippedExceptionIfNonOperational(); + + // IPv4 and IPv6 interfaces that support multicasting + NetworkConfiguration config = NetworkConfiguration.probe(); + List ip4MulticastInterfaces = config.ip4MulticastInterfaces() + .collect(Collectors.toList()); + List ip6MulticastInterfaces = config.ip6MulticastInterfaces() + .collect(Collectors.toList()); + + // multicast groups used for the test + InetAddress ip4Group = InetAddress.getByName("225.4.5.6"); + InetAddress ip6Group = InetAddress.getByName("ff02::a"); + + for (NetworkInterface ni : ip4MulticastInterfaces) { + test(INET, ip4Group, ni); + if (IPSupport.hasIPv6()) { + test(UNSPEC, ip4Group, ni); + test(INET6, ip4Group, ni); + } + } + for (NetworkInterface ni : ip6MulticastInterfaces) { + test(UNSPEC, ip6Group, ni); + test(INET6, ip6Group, ni); + } + } + + static void test(ProtocolFamily family, InetAddress mcastaddr, NetworkInterface ni) + throws IOException + { + System.out.format("Test family=%s, multicast group=%s, interface=%s%n", + family.name(), mcastaddr, ni.getName()); + + // An instance of DatagramSocket can also be used to receive + // multicast datagram packets. A DatagramSocket that is created + // with the intent of receiving multicast datagrams should be + // created unbound. Before binding the socket, setReuseAddress(true) + // should be configured: + try (DatagramSocket socket = new DatagramSocket(null); // unbound + DatagramSocket sender = new DatagramSocket(new InetSocketAddress(0))) { + + socket.setReuseAddress(true); + socket.bind(new InetSocketAddress(0)); + + // joinGroup + // InetAddress mcastaddr = InetAddress.getByName("228.5.6.7"); + InetSocketAddress group = new InetSocketAddress(mcastaddr, 0); + // NetworkInterface netIf = NetworkInterface.getByName("en0"); + NetworkInterface netIf = ni; + + socket.joinGroup(group, netIf); + try { + byte[] rcvBytes = new byte[1024]; // up to 1024 bytes + DatagramPacket packet = new DatagramPacket(rcvBytes, rcvBytes.length); + + // An instance of DatagramSocket can be used to send or receive + // multicast datagram packets. Before sending out datagram packets, + // the default outgoing interface for sending datagram packets + // should be configured first using setOption and + // StandardSocketOptions.IP_MULTICAST_IF: + + // DatagramSocket sender = new DatagramSocket(new InetSocketAddress(0)); + // NetworkInterface outgoingIf = NetworkInterface.getByName("en0"); + NetworkInterface outgoingIf = ni; + sender.setOption(StandardSocketOptions.IP_MULTICAST_IF, outgoingIf); + + // optionally configure multicast TTL + int ttl = 1; // a number betwen 0 and 255 + sender.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl); + + // send a packet to a multicast group + byte[] msgBytes = "Hello".getBytes(StandardCharsets.UTF_8); + int port = socket.getLocalPort(); + InetSocketAddress dest = new InetSocketAddress(mcastaddr, port); + DatagramPacket hi = new DatagramPacket(msgBytes, msgBytes.length, dest); + sender.send(hi); + + socket.receive(packet); + byte[] bytes = Arrays.copyOfRange(packet.getData(), 0, packet.getLength()); + assertTrue("Hello".equals(new String(bytes, StandardCharsets.UTF_8))); + } finally { + // eventually leave group + socket.leaveGroup(group, netIf); + } + } + + } + + static void assertTrue(boolean e) { + if (!e) throw new RuntimeException(); + } + + interface ThrowableRunnable { + void run() throws Exception; + } + + static void assertThrows(java.lang.Class exceptionClass, ThrowableRunnable task) { + try { + task.run(); + throw new RuntimeException("Exception not thrown"); + } catch (Exception e) { + if (!exceptionClass.isInstance(e)) { + throw new RuntimeException("expected: " + exceptionClass + ", actual: " + e); + } + } + } +} diff --git a/test/jdk/java/net/DatagramSocket/DatagramSocketMulticasting.java b/test/jdk/java/net/DatagramSocket/DatagramSocketMulticasting.java new file mode 100644 index 00000000000..b3b8918a392 --- /dev/null +++ b/test/jdk/java/net/DatagramSocket/DatagramSocketMulticasting.java @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8237352 + * @summary Test DatagramSocket for sending and receiving multicast datagrams + * @library /test/lib + * @build jdk.test.lib.NetworkConfiguration + * jdk.test.lib.net.IPSupport + * @run main/othervm DatagramSocketMulticasting + * @run main/othervm -Djava.net.preferIPv4Stack=true DatagramSocketMulticasting + * @run main/othervm -Djdk.usePlainDatagramSocketImpl=true DatagramSocketMulticasting + * @run main/othervm -Djdk.usePlainDatagramSocketImpl=true -Djava.net.preferIPv4Stack=true DatagramSocketMulticasting + */ + +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.MulticastSocket; +import java.net.NetworkInterface; +import java.net.ProtocolFamily; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.SocketOption; +import java.net.SocketTimeoutException; +import java.nio.channels.DatagramChannel; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import jdk.test.lib.NetworkConfiguration; +import jdk.test.lib.net.IPSupport; + +import static java.net.StandardProtocolFamily.INET; +import static java.net.StandardProtocolFamily.INET6; +import static java.net.StandardSocketOptions.IP_MULTICAST_IF; +import static java.net.StandardSocketOptions.IP_MULTICAST_LOOP; +import static java.net.StandardSocketOptions.IP_MULTICAST_TTL; +import static java.net.StandardSocketOptions.SO_REUSEADDR; + +public class DatagramSocketMulticasting { + static final ProtocolFamily UNSPEC = () -> "UNSPEC"; + + public static void main(String[] args) throws IOException { + IPSupport.throwSkippedExceptionIfNonOperational(); + + // IPv4 and IPv6 interfaces that support multicasting + NetworkConfiguration config = NetworkConfiguration.probe(); + List ip4MulticastInterfaces = config.ip4MulticastInterfaces() + .collect(Collectors.toList()); + List ip6MulticastInterfaces = config.ip6MulticastInterfaces() + .collect(Collectors.toList()); + + // multicast groups used for the test + InetAddress ip4Group = InetAddress.getByName("225.4.5.6"); + InetAddress ip6Group = InetAddress.getByName("ff02::a"); + + for (NetworkInterface ni : ip4MulticastInterfaces) { + test(INET, ip4Group, ni); + if (IPSupport.hasIPv6()) { + test(UNSPEC, ip4Group, ni); + test(INET6, ip4Group, ni); + } + } + for (NetworkInterface ni : ip6MulticastInterfaces) { + test(UNSPEC, ip6Group, ni); + test(INET6, ip6Group, ni); + } + } + + static void test(ProtocolFamily family, InetAddress group, NetworkInterface ni) + throws IOException + { + System.out.format("Test family=%s, multicast group=%s, interface=%s%n", + family.name(), group, ni.getName()); + + // test 2-arg joinGroup/leaveGroup + try (DatagramSocket s = create()) { + testJoinGroup2(family, s, group, ni); + } + + // test socket options + try (DatagramSocket s = create()) { + testNetworkInterface(s, ni); + testTimeToLive(s); + testLoopbackMode(s); + } + } + + /** + * Creates a MulticastSocket. The SO_REUSEADDR socket option is set and it + * is bound to the wildcard address. + */ + static DatagramSocket create() throws IOException { + DatagramSocket ds = new DatagramSocket(null); + try { + ds.setOption(SO_REUSEADDR, true).bind(new InetSocketAddress(0)); + } catch (IOException ioe) { + ds.close(); + throw ioe; + } + return ds; + } + + /** + * Test 2-arg joinGroup/leaveGroup + */ + static void testJoinGroup2(ProtocolFamily family, + DatagramSocket s, + InetAddress group, + NetworkInterface ni) throws IOException { + + System.out.format("testJoinGroup2: local socket address: %s%n", s.getLocalSocketAddress()); + + // check network interface not set + assertTrue(s.getOption(IP_MULTICAST_IF) == null); + + // join on default interface + s.joinGroup(new InetSocketAddress(group, 0), null); + + // join should not change the outgoing multicast interface + assertTrue(s.getOption(IP_MULTICAST_IF) == null); + + // already a member (exception not specified) + assertThrows(SocketException.class, + () -> s.joinGroup(new InetSocketAddress(group, 0), null)); + + // leave + s.leaveGroup(new InetSocketAddress(group, 0), null); + + // not a member (exception not specified) + assertThrows(SocketException.class, + () -> s.leaveGroup(new InetSocketAddress(group, 0), null)); + + // join on specified interface + s.joinGroup(new InetSocketAddress(group, 0), ni); + + // join should not change the outgoing multicast interface + assertTrue(s.getOption(IP_MULTICAST_IF) == null); + + // already a member (exception not specified) + assertThrows(SocketException.class, + () -> s.joinGroup(new InetSocketAddress(group, 0), ni)); + + // leave + s.leaveGroup(new InetSocketAddress(group, 0), ni); + + // not a member (exception not specified) + assertThrows(SocketException.class, + () -> s.leaveGroup(new InetSocketAddress(group, 0), ni)); + + // join/leave with outgoing multicast interface set and check that + // multicast datagrams can be sent and received + s.setOption(IP_MULTICAST_IF, ni); + s.joinGroup(new InetSocketAddress(group, 0), null); + testSendReceive(s, group); + s.leaveGroup(new InetSocketAddress(group, 0), null); + testSendNoReceive(s, group); + s.joinGroup(new InetSocketAddress(group, 0), ni); + testSendReceive(s, group); + s.leaveGroup(new InetSocketAddress(group, 0), ni); + testSendNoReceive(s, group); + + // not a multicast address + var localHost = InetAddress.getLocalHost(); + assertThrows(SocketException.class, + () -> s.joinGroup(new InetSocketAddress(localHost, 0), null)); + assertThrows(SocketException.class, + () -> s.leaveGroup(new InetSocketAddress(localHost, 0), null)); + assertThrows(SocketException.class, + () -> s.joinGroup(new InetSocketAddress(localHost, 0), ni)); + assertThrows(SocketException.class, + () -> s.leaveGroup(new InetSocketAddress(localHost, 0), ni)); + + // not an InetSocketAddress + var customSocketAddress = new SocketAddress() { }; + assertThrows(IllegalArgumentException.class, + () -> s.joinGroup(customSocketAddress, null)); + assertThrows(IllegalArgumentException.class, + () -> s.leaveGroup(customSocketAddress, null)); + assertThrows(IllegalArgumentException.class, + () -> s.joinGroup(customSocketAddress, ni)); + assertThrows(IllegalArgumentException.class, + () -> s.leaveGroup(customSocketAddress, ni)); + + // IPv4 socket cannot join IPv6 group + if (family == INET && !IPSupport.hasIPv6()) { + System.out.println("Test IPv4 can't join IPv6"); + InetAddress ip6Group = InetAddress.getByName("ff02::a"); + assertThrows(IllegalArgumentException.class, + () -> s.joinGroup(new InetSocketAddress(ip6Group, 0), null)); + assertThrows(IllegalArgumentException.class, + () -> s.joinGroup(new InetSocketAddress(ip6Group, 0), ni)); + + // not a member of IPv6 group (exception not specified) + assertThrows(SocketException.class, + () -> s.leaveGroup(new InetSocketAddress(ip6Group, 0), null)); + assertThrows(SocketException.class, + () -> s.leaveGroup(new InetSocketAddress(ip6Group, 0), ni)); + } + + // null + assertThrows(IllegalArgumentException.class, () -> s.joinGroup(null, null)); + assertThrows(IllegalArgumentException.class, () -> s.leaveGroup(null, null)); + assertThrows(IllegalArgumentException.class, () -> s.joinGroup(null, ni)); + assertThrows(IllegalArgumentException.class, () -> s.leaveGroup(null, ni)); + } + + /** + * Test getNetworkInterface/setNetworkInterface/getInterface/setInterface + * and IP_MULTICAST_IF socket option. + */ + static void testNetworkInterface(DatagramSocket s, + NetworkInterface ni) throws IOException { + // default value + assertTrue(s.getOption(IP_MULTICAST_IF) == null); + + // setOption(IP_MULTICAST_IF) + s.setOption(IP_MULTICAST_IF, ni); + assertTrue(s.getOption(IP_MULTICAST_IF).equals(ni)); + + // bad values for IP_MULTICAST_IF + assertThrows(IllegalArgumentException.class, + () -> s.setOption(IP_MULTICAST_IF, null)); + assertThrows(IllegalArgumentException.class, + () -> s.setOption((SocketOption) IP_MULTICAST_IF, "badValue")); + } + + /** + * Test getTimeToLive/setTimeToLive/getTTL/getTTL and IP_MULTICAST_TTL socket + * option. + */ + static void testTimeToLive(DatagramSocket s) throws IOException { + // should be 1 by default + assertTrue(s.getOption(IP_MULTICAST_TTL) == 1); + + // setOption(IP_MULTICAST_TTL) + for (int ttl = 0; ttl <= 2; ttl++) { + s.setOption(IP_MULTICAST_TTL, ttl); + assertTrue(s.getOption(IP_MULTICAST_TTL) == ttl); + } + + // bad values for IP_MULTICAST_TTL + assertThrows(IllegalArgumentException.class, + () -> s.setOption(IP_MULTICAST_TTL, -1)); + assertThrows(IllegalArgumentException.class, + () -> s.setOption(IP_MULTICAST_TTL, null)); + assertThrows(IllegalArgumentException.class, + () -> s.setOption((SocketOption) IP_MULTICAST_TTL, "badValue")); + } + + /** + * Test getLoopbackMode/setLoopbackMode and IP_MULTICAST_LOOP socket option. + */ + static void testLoopbackMode(DatagramSocket s) throws IOException { + // should be enabled by default + assertTrue(s.getOption(IP_MULTICAST_LOOP) == true); + + // setLoopbackMode + + // setOption(IP_MULTICAST_LOOP) + s.setOption(IP_MULTICAST_LOOP, false); // disable + assertTrue(s.getOption(IP_MULTICAST_LOOP) == false); + s.setOption(IP_MULTICAST_LOOP, true); // enable + assertTrue(s.getOption(IP_MULTICAST_LOOP) == true); + + // bad values for IP_MULTICAST_LOOP + assertThrows(IllegalArgumentException.class, + () -> s.setOption(IP_MULTICAST_LOOP, null)); + assertThrows(IllegalArgumentException.class, + () -> s.setOption((SocketOption) IP_MULTICAST_LOOP, "badValue")); + } + + /** + * Send a datagram to the given multicast group and check that it is received. + */ + static void testSendReceive(DatagramSocket s, InetAddress group) throws IOException { + + System.out.println("testSendReceive"); + + // outgoing multicast interface needs to be set + assertTrue(s.getOption(IP_MULTICAST_IF) != null); + + SocketAddress target = new InetSocketAddress(group, s.getLocalPort()); + byte[] message = "hello".getBytes("UTF-8"); + + // send message to multicast group + DatagramPacket p = new DatagramPacket(message, message.length); + p.setSocketAddress(target); + s.send(p); + + // receive message + s.setSoTimeout(0); + p = new DatagramPacket(new byte[1024], 100); + s.receive(p); + + assertTrue(p.getLength() == message.length); + assertTrue(p.getPort() == s.getLocalPort()); + } + + /** + * Send a datagram to the given multicast group and check that it is not + * received. + */ + static void testSendNoReceive(DatagramSocket s, InetAddress group) throws IOException { + + System.out.println("testSendNoReceive"); + + // outgoing multicast interface needs to be set + assertTrue(s.getOption(IP_MULTICAST_IF) != null); + + SocketAddress target = new InetSocketAddress(group, s.getLocalPort()); + long nano = System.nanoTime(); + String text = nano + ": hello"; + byte[] message = text.getBytes("UTF-8"); + + // send datagram to multicast group + DatagramPacket p = new DatagramPacket(message, message.length); + p.setSocketAddress(target); + s.send(p); + + // datagram should not be received + s.setSoTimeout(500); + p = new DatagramPacket(new byte[1024], 100); + while (true) { + try { + s.receive(p); + if (Arrays.equals(p.getData(), p.getOffset(), p.getLength(), message, 0, message.length)) { + throw new RuntimeException("message shouldn't have been received"); + } else { + System.out.format("Received unexpected message from %s%n", p.getSocketAddress()); + } + } catch (SocketTimeoutException expected) { + break; + } + } + } + + + static void assertTrue(boolean e) { + if (!e) throw new RuntimeException(); + } + + interface ThrowableRunnable { + void run() throws Exception; + } + + static void assertThrows(Class exceptionClass, ThrowableRunnable task) { + try { + task.run(); + throw new RuntimeException("Exception not thrown"); + } catch (Exception e) { + if (!exceptionClass.isInstance(e)) { + throw new RuntimeException("expected: " + exceptionClass + ", actual: " + e); + } + } + } +} diff --git a/test/jdk/java/nio/channels/unixdomain/FileAttributes.java b/test/jdk/java/nio/channels/unixdomain/FileAttributes.java new file mode 100644 index 00000000000..3ff92a6bc05 --- /dev/null +++ b/test/jdk/java/nio/channels/unixdomain/FileAttributes.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8252971 + * @library /test/lib + * @run testng FileAttributes + */ + +import java.io.IOException; +import java.io.File; +import java.net.*; +import java.nio.channels.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Arrays; +import org.testng.annotations.Test; +import org.testng.SkipException; + +import static java.net.StandardProtocolFamily.UNIX; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertThrows; +import static org.testng.Assert.assertTrue; + +/** + */ +public class FileAttributes { + + @Test + public static void test() throws Exception { + checkSupported(); + Path path = null; + try (var chan = SocketChannel.open(UNIX)) { + path = Path.of("foo.sock"); + var addr = UnixDomainSocketAddress.of(path); + + chan.bind(addr); + + // Check file exists + + File f = path.toFile(); + assertTrue(f.exists(), "File.exists failed"); + + assertTrue(Files.exists(path), "Files.exists failed"); + + // Check basic attributes + BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class); + + assertFalse(attrs.isDirectory(), "file is not a directory"); + assertTrue(attrs.isOther(), "file is other"); + assertFalse(attrs.isRegularFile(), "file is not a regular file"); + assertFalse(attrs.isSymbolicLink(), "file is not a symbolic link"); + + // Check can't copy + final Path src = path; + final Path dest = Path.of("bar.sock"); + assertThrows(IOException.class, () -> Files.copy(src, dest)); + + // Check deletion + assertTrue(f.delete(), "File.delete failed"); + } finally { + Files.deleteIfExists(path); + } + } + + static void checkSupported() { + try { + SocketChannel.open(UNIX).close(); + } catch (UnsupportedOperationException e) { + throw new SkipException("Unix domain channels not supported"); + } catch (Exception e) { + // continue test to see what problem is + } + } +} diff --git a/test/jdk/java/nio/channels/unixdomain/Security.java b/test/jdk/java/nio/channels/unixdomain/Security.java index 06f52ec33b3..a207cd814e9 100644 --- a/test/jdk/java/nio/channels/unixdomain/Security.java +++ b/test/jdk/java/nio/channels/unixdomain/Security.java @@ -162,6 +162,7 @@ public static void testPolicy2() throws Exception { public static void testPolicy3() throws Exception { Path sock1 = Path.of("sock3"); + Path sock2 = null; Files.deleteIfExists(sock1); final UnixDomainSocketAddress saddr = UnixDomainSocketAddress.of(sock1); try (var s1 = ServerSocketChannel.open(UNIX)) { @@ -169,8 +170,7 @@ public static void testPolicy3() throws Exception { try (var s2 = ServerSocketChannel.open(UNIX)) { s2.bind(null); var add2 = (UnixDomainSocketAddress)s2.getLocalAddress(); - saddr.getPath().toFile().deleteOnExit(); - add2.getPath().toFile().deleteOnExit(); + sock2 = add2.getPath(); // Now set security manager and check if we can see addresses @@ -194,6 +194,10 @@ public static void testPolicy3() throws Exception { throw new RuntimeException("address should have been empty"); } } + } finally { + System.setSecurityManager(null); + Files.deleteIfExists(sock1); + Files.deleteIfExists(sock2); } } } diff --git a/test/jdk/java/nio/channels/unixdomain/policy3 b/test/jdk/java/nio/channels/unixdomain/policy3 index ccfe2ef15a7..89edb67117a 100644 --- a/test/jdk/java/nio/channels/unixdomain/policy3 +++ b/test/jdk/java/nio/channels/unixdomain/policy3 @@ -23,4 +23,6 @@ grant { // No permission permission java.io.FilePermission "sock", "delete"; + + permission java.lang.RuntimePermission "setSecurityManager"; }; diff --git a/test/jdk/java/util/ResourceBundle/Control/DefaultControlTest.java b/test/jdk/java/util/ResourceBundle/Control/DefaultControlTest.java index c5c41a5c3d2..2605db66940 100644 --- a/test/jdk/java/util/ResourceBundle/Control/DefaultControlTest.java +++ b/test/jdk/java/util/ResourceBundle/Control/DefaultControlTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* * @test - * @bug 5102289 6278334 + * @bug 5102289 6278334 8261179 * @summary Test the default Control implementation. The expiration * functionality of newBundle, getTimeToLive, and needsReload is * tested by ExpirationTest.sh. The factory methods are tested @@ -145,31 +145,50 @@ private static void testGetCandidateLocales() { new Locale("ja", "JP", "YOK"), new Locale("ja", "JP"), new Locale("ja"), - new Locale("") }); + Locale.ROOT }); candidateData.put(new Locale("ja", "JP"), new Locale[] { new Locale("ja", "JP"), new Locale("ja"), - new Locale("") }); + Locale.ROOT }); candidateData.put(new Locale("ja"), new Locale[] { new Locale("ja"), - new Locale("") }); + Locale.ROOT }); candidateData.put(new Locale("ja", "", "YOK"), new Locale[] { new Locale("ja", "", "YOK"), new Locale("ja"), - new Locale("") }); + Locale.ROOT }); candidateData.put(new Locale("", "JP", "YOK"), new Locale[] { new Locale("", "JP", "YOK"), new Locale("", "JP"), - new Locale("") }); + Locale.ROOT }); candidateData.put(new Locale("", "", "YOK"), new Locale[] { new Locale("", "", "YOK"), - new Locale("") }); + Locale.ROOT }); candidateData.put(new Locale("", "JP"), new Locale[] { new Locale("", "JP"), - new Locale("") }); - candidateData.put(new Locale(""), new Locale[] { - new Locale("") }); + Locale.ROOT }); + candidateData.put(Locale.ROOT, new Locale[] { + Locale.ROOT }); + + // Norwegian Bokmal + candidateData.put(Locale.forLanguageTag("nb-NO-POSIX"), new Locale[] { + Locale.forLanguageTag("nb-NO-POSIX"), + Locale.forLanguageTag("no-NO-POSIX"), + Locale.forLanguageTag("nb-NO"), + Locale.forLanguageTag("no-NO"), + Locale.forLanguageTag("nb"), + Locale.forLanguageTag("no"), + Locale.ROOT}); + candidateData.put(Locale.forLanguageTag("no-NO-POSIX"), new Locale[] { + Locale.forLanguageTag("no-NO-POSIX"), + Locale.forLanguageTag("nb-NO-POSIX"), + Locale.forLanguageTag("no-NO"), + Locale.forLanguageTag("nb-NO"), + Locale.forLanguageTag("no"), + Locale.forLanguageTag("nb"), + Locale.ROOT}); + for (Locale locale : candidateData.keySet()) { List candidates = CONTROL.getCandidateLocales("any", locale); @@ -233,7 +252,7 @@ private static void testNewBundle() { } testNo = 2; - rb = CONTROL.newBundle("TestResourceRB", new Locale(""), + rb = CONTROL.newBundle("TestResourceRB", Locale.ROOT, CLAZZ, LOADER, false); s = rb.getString("type"); if (!s.equals(CLAZZ)) { @@ -267,7 +286,7 @@ private static void testNewBundle() { } try { - rb = CONTROL.newBundle("NonResourceBundle", new Locale(""), + rb = CONTROL.newBundle("NonResourceBundle", Locale.ROOT, "java.class", LOADER, false); error("newBundle: doesn't throw ClassCastException with a non-ResourceBundle subclass."); } catch (ClassCastException cce) { @@ -349,7 +368,7 @@ private static void testToBundleName() { name + "_" + "" + "_" + "" + "_" + "YOK"); bundleNames.put(new Locale("", "JP"), name + "_" + "" + "_" + "JP"); - bundleNames.put(new Locale(""), + bundleNames.put(Locale.ROOT, name); for (Locale locale : bundleNames.keySet()) { diff --git a/test/jdk/java/util/regex/TestCases.txt b/test/jdk/java/util/regex/TestCases.txt index 9461f57dc2d..3b367782643 100644 --- a/test/jdk/java/util/regex/TestCases.txt +++ b/test/jdk/java/util/regex/TestCases.txt @@ -25,7 +25,7 @@ // A test case consists of three lines: // The first line is a pattern used in the test // The second line is the input to search for the pattern in -// The third line is a concatentation of the match, the number of groups, +// The third line is a concatenation of the match, the number of groups, // and the contents of the first four subexpressions. // Empty lines and lines beginning with comment slashes are ignored. // @@ -1231,3 +1231,45 @@ true 1 (|f){0,1}+ foo true 1 + +//---------------------------------------------------------------- +// Unary numeral primality testing +//---------------------------------------------------------------- + +// Input is 7 (a prime), in unary; reluctant quantifier +^(11+?)\1+$ +1111111 +false 1 + +^(1{2,}?)\1+$ +1111111 +false 1 + +// Input is 8 (a power of two), in unary; reluctant quantifier +// group is shortest possible (2) +^(11+?)\1+$ +11111111 +true 11111111 1 11 + +^(1{2,}?)\1+$ +11111111 +true 11111111 1 11 + +// Input is 7 (a prime), in unary; greedy quantifier +^(11+)\1+$ +1111111 +false 1 + +^(1{2,})\1+$ +1111111 +false 1 + +// Input is 8 (a power of two), in unary; greedy quantifier +// group is longest possible (4) +^(11+)\1+$ +11111111 +true 11111111 1 1111 + +^(1{2,})\1+$ +11111111 +true 11111111 1 1111 diff --git a/test/jdk/javax/net/ssl/SSLSession/TestEnabledProtocols.java b/test/jdk/javax/net/ssl/SSLSession/TestEnabledProtocols.java index cd8ad678b47..e0b7fd7ec35 100644 --- a/test/jdk/javax/net/ssl/SSLSession/TestEnabledProtocols.java +++ b/test/jdk/javax/net/ssl/SSLSession/TestEnabledProtocols.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,8 @@ import java.io.InputStream; import java.io.InterruptedIOException; import java.io.OutputStream; +import java.net.InetAddress; +import java.net.SocketException; import java.security.Security; import java.util.Arrays; @@ -63,6 +65,7 @@ public TestEnabledProtocols(String[] serverProtocols, this.clientProtocols = clientProtocols; this.exceptionExpected = exceptionExpected; this.selectedProtocol = selectedProtocol; + this.serverAddress = InetAddress.getLoopbackAddress(); } @Override @@ -126,25 +129,40 @@ protected void runClientApplication(SSLSocket sslSocket) throws Exception { out.write(280); } catch (SSLHandshakeException e) { if (!exceptionExpected) { - System.out.println( - "Client got UNEXPECTED SSLHandshakeException:"); - e.printStackTrace(System.out); - System.out.println("** FAILURE **"); - throw new RuntimeException(e); + failTest(e, "Client got UNEXPECTED SSLHandshakeException:"); } else { System.out.println( "Client got expected SSLHandshakeException:"); e.printStackTrace(System.out); System.out.println("** Success **"); } + } catch (SSLException ssle) { + // The server side may have closed the socket. + if (isConnectionReset(ssle)) { + System.out.println("Client SSLException:"); + ssle.printStackTrace(System.out); + } else { + failTest(ssle, "Client got UNEXPECTED SSLException:"); + } + } catch (Exception e) { - System.out.println("Client got UNEXPECTED Exception:"); - e.printStackTrace(System.out); - System.out.println("** FAILURE **"); - throw new RuntimeException(e); + failTest(e, "Client got UNEXPECTED Exception:"); } } + private boolean isConnectionReset(SSLException ssle) { + Throwable cause = ssle.getCause(); + return cause instanceof SocketException + && "Connection reset".equals(cause.getMessage()); + } + + private void failTest(Exception e, String message) { + System.out.println(message); + e.printStackTrace(System.out); + System.out.println("** FAILURE **"); + throw new RuntimeException(e); + } + public static void main(String[] args) throws Exception { Security.setProperty("jdk.tls.disabledAlgorithms", ""); diff --git a/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java b/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java index 4e09eea3f3b..d1322715749 100644 --- a/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java +++ b/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.security.KeyFactory; import java.security.KeyStore; import java.security.PrivateKey; @@ -206,8 +208,11 @@ void doServerSide() throws Exception { keyType.getTrustedCert(), keyType.getEndCert(), keyType.getPrivateKey(), keyType.getKeyType()); SSLServerSocketFactory sslssf = ctx.getServerSocketFactory(); + InetSocketAddress socketAddress = + new InetSocketAddress(InetAddress.getLoopbackAddress(), port); SSLServerSocket sslServerSocket - = (SSLServerSocket) sslssf.createServerSocket(port); + = (SSLServerSocket) sslssf.createServerSocket(); + sslServerSocket.bind(socketAddress); port = sslServerSocket.getLocalPort(); System.out.println("Server listining on port: " + port); // specify the enabled server cipher suites diff --git a/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java b/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java new file mode 100644 index 00000000000..b63973229a2 --- /dev/null +++ b/test/jdk/javax/swing/JCheckBox/ImageCheckboxFocus/ImageCheckboxTest.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.File; +import javax.imageio.ImageIO; +import javax.swing.Icon; +import javax.swing.JCheckBox; + +/* + * @test + * @key headful + * @bug 8216358 + * @summary [macos] The focus is invisible when tab to "Image Radio Buttons" and "Image CheckBoxes" + * @library ../../regtesthelpers/ + * @build Util + * @run main ImageCheckboxTest + */ + +public class ImageCheckboxTest { + public static void main(String[] args) throws Exception { + new ImageCheckboxTest().performTest(); + } + + public void performTest() throws Exception { + BufferedImage imageNoFocus = new BufferedImage(100, 50, + BufferedImage.TYPE_INT_ARGB); + BufferedImage imageFocus = new BufferedImage(100, 50, + BufferedImage.TYPE_INT_ARGB); + + CustomCheckBox checkbox = new CustomCheckBox("Test", new MyIcon(Color.GREEN)); + checkbox.setSize(100, 50); + checkbox.setFocused(false); + checkbox.paint(imageNoFocus.createGraphics()); + checkbox.setFocused(true); + checkbox.paint(imageFocus.createGraphics()); + + if (Util.compareBufferedImages(imageFocus, imageNoFocus)) { + ImageIO.write(imageFocus, "png", new File("imageFocus.png")); + ImageIO.write(imageNoFocus, "png", new File("imageNoFocus.png")); + throw new Exception("Changing focus is not visualized"); + } + } + + class MyIcon implements Icon { + Color color; + public MyIcon(Color color) { + this.color = color; + } + + @Override + public void paintIcon(Component c, Graphics g, int x, int y) { + Color old = g.getColor(); + g.setColor(color); + g.fillArc(x+2, y+2, 12, 12, 0, 360); + g.setColor(old); + } + + @Override + public int getIconWidth() { + return 18; + } + + @Override + public int getIconHeight() { + return 18; + } + } + + class CustomCheckBox extends JCheckBox { + public CustomCheckBox(String label, Icon icon) { + super(label, icon); + } + + private boolean focused = false; + public void setFocused(boolean focused) { + this.focused = focused; + } + + @Override + public boolean hasFocus() { + return focused; + } + } +} diff --git a/test/jdk/javax/swing/JSpinner/TestJSpinnerPressUnpress.java b/test/jdk/javax/swing/JSpinner/TestJSpinnerPressUnpress.java index 6191b35ce13..20c7dac84a6 100644 --- a/test/jdk/javax/swing/JSpinner/TestJSpinnerPressUnpress.java +++ b/test/jdk/javax/swing/JSpinner/TestJSpinnerPressUnpress.java @@ -101,7 +101,6 @@ private static void createUI() { JTextArea instructionTextArea = new JTextArea(); instructionTextArea.setText(INSTRUCTIONS); instructionTextArea.setEditable(false); - instructionTextArea.setBackground(Color.white); gbc.gridx = 0; gbc.gridy = 1; diff --git a/test/jdk/javax/swing/text/html/CSS/4765271/bug4765271.java b/test/jdk/javax/swing/text/html/CSS/4765271/bug4765271.java new file mode 100644 index 00000000000..91115cf5ab3 --- /dev/null +++ b/test/jdk/javax/swing/text/html/CSS/4765271/bug4765271.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Font; +import java.awt.Shape; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.text.AbstractDocument.AbstractElement; +import javax.swing.text.AttributeSet; +import javax.swing.text.View; +import javax.swing.text.html.HTMLDocument; +import javax.swing.text.html.HTMLEditorKit; +import javax.swing.text.html.StyleSheet; + +/* + * @test + * @bug 4765271 8231286 + * @summary Tests if JEditorPane displays text with proper size + * @run main bug4765271 + */ +public class bug4765271 { + + // The default resolution for screen + private static final int RES = 96; + + private static final String TEXT = + "" + + "" + + "A" + + "B" + + "C" + + "D" + + "E" + + "F" + + "" + + ""; + + private JEditorPane jep; + + private final boolean showFrame; + private final AtomicBoolean passed = new AtomicBoolean(true); + + public bug4765271(boolean showFrame) { + this.showFrame = showFrame; + } + + public void init() { + System.out.println("res = " + RES); + + jep = new JEditorPane(); + jep.putClientProperty(JEditorPane.W3C_LENGTH_UNITS, Boolean.TRUE); + jep.setEditorKit(new HTMLEditorKit()); + jep.setEditable(false); + + jep.setText(TEXT); + + if (showFrame) { + JFrame f = new JFrame("Reg test for bug4765271"); + f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + f.getContentPane().add(jep); + f.pack(); + f.setVisible(true); + } else { + jep.setSize(jep.getPreferredSize()); + } + } + + public void test() { + Shape r = jep.getBounds(); + View v = jep.getUI().getRootView(jep); + while (!(v instanceof javax.swing.text.html.InlineView)) { + String viewName = v.getClass().getName(); + int n = v.getViewCount(); + if (viewName.endsWith("Row")) { + break; + } + Shape sh = v.getChildAllocation(n - 1, r); + if (sh != null) { + r = sh; + } + v = v.getView(n - 1); + } + + Shape sh = v.getChildAllocation(0, r); + int h1 = sh.getBounds().height; + StyleSheet ss = ((HTMLDocument) v.getDocument()).getStyleSheet(); + View childView = v.getView(0); + AttributeSet attrs = childView.getAttributes(); + Font font = ss.getFont(attrs); + int size1 = font.getSize(); + System.out.println("Font Size for InlineView #0 = " + size1 + "; height = " + h1 + "; element = {"); + ((AbstractElement) childView.getElement()).dump(System.out, 3); + System.out.println("}"); + + boolean testPassed = true; + int n = v.getViewCount() - 1; + for (int i = 1; i < n; i++) { + sh = v.getChildAllocation(i, r); + int h2 = sh.getBounds().height; + childView = v.getView(i); + attrs = childView.getAttributes(); + font = ss.getFont(attrs); + int size2 = font.getSize(); + System.out.println("Font Size for InlineView #" + i + " = " + size2 + "; height = " + h2 + "; element = {"); + ((AbstractElement) childView.getElement()).dump(System.out, 3); + System.out.println("}"); + testPassed &= ((size1 == size2) && (h1 == h2)); + } + passed.set(testPassed); + } + + public static void main(String[] args) throws Exception { + bug4765271 test = new bug4765271( + (args.length > 0) && "-show".equals(args[0])); + + SwingUtilities.invokeAndWait(() -> { + test.init(); + test.test(); + }); + + if (!test.passed.get()) { + throw new RuntimeException("Test failed"); + } else { + System.out.println("Test succeeded"); + } + } +} diff --git a/test/jdk/javax/swing/text/html/CSS/8231286/HtmlFontSizeTest.java b/test/jdk/javax/swing/text/html/CSS/8231286/HtmlFontSizeTest.java new file mode 100644 index 00000000000..9bdf4dbfae8 --- /dev/null +++ b/test/jdk/javax/swing/text/html/CSS/8231286/HtmlFontSizeTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * @test + * @bug 8231286 + * @summary Verifies if HTML font size too large with high-DPI scaling and W3C_LENGTH_UNITS + * @run main/othervm -Dsun.java2d.uiScale=1.0 HtmlFontSizeTest + */ + +import java.awt.Dimension; +import java.util.Locale; + +import javax.swing.JEditorPane; +import javax.swing.SwingUtilities; +import javax.swing.text.Document; +import javax.swing.text.html.HTMLEditorKit; + +public class HtmlFontSizeTest { + static volatile Dimension w3cFrameSize; + static volatile Dimension stdFrameSize; + + private static Dimension test(boolean w3ccheck) { + JEditorPane htmlPane = new JEditorPane(); + htmlPane.setEditable(false); + + if (w3ccheck) { + htmlPane.putClientProperty(JEditorPane.W3C_LENGTH_UNITS, Boolean.TRUE); + } + + HTMLEditorKit kit = new HTMLEditorKit(); + htmlPane.setEditorKit(kit); + + String htmlString = "\n" + + "\n" + + "

    This should be 16 pt.

    \n" + + "\n" + + ""; + + Document doc = kit.createDefaultDocument(); + htmlPane.setDocument(doc); + htmlPane.setText(htmlString); + + return htmlPane.getPreferredSize(); + } + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> { + w3cFrameSize = test(true); + stdFrameSize = test(false); + }); + System.out.println("size with W3C:" + w3cFrameSize); + System.out.println("size without W3C:" + stdFrameSize); + + float ratio = (float)w3cFrameSize.width / (float)stdFrameSize.width; + System.out.println("w3cFrameSize.width/stdFrameSize.width " + ratio); + + if (!"1.3".equals(String.format(Locale.ENGLISH, "%.1f", ratio))) { + throw new RuntimeException("HTML font size too large with high-DPI scaling and W3C_LENGTH_UNITS"); + } + } +} diff --git a/test/jdk/javax/swing/text/html/StyleSheet/8260687/BodyInheritedFontSize.java b/test/jdk/javax/swing/text/html/StyleSheet/8260687/BodyInheritedFontSize.java new file mode 100644 index 00000000000..50030df2082 --- /dev/null +++ b/test/jdk/javax/swing/text/html/StyleSheet/8260687/BodyInheritedFontSize.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.SwingUtilities; +import javax.swing.text.AbstractDocument.AbstractElement; +import javax.swing.text.Document; +import javax.swing.text.GlyphView; +import javax.swing.text.View; +import javax.swing.text.html.HTMLEditorKit; +import javax.swing.text.html.StyleSheet; + +/* + * @test + * @bug 8260687 + * @summary Tests inherited font-size is the same as explicitly specified + * @run main BodyInheritedFontSize + */ +public class BodyInheritedFontSize { + private static final String HTML_TEXT = """ + + +

    100% from body

    +

    16pt inherited from body

    +

    16pt paragraph

    + + + """; + + private static JEditorPane createEditorPane(boolean w3cUnits, boolean showFrame) { + JEditorPane htmlPane = new JEditorPane(); + htmlPane.setEditable(false); + + if (w3cUnits) { + htmlPane.putClientProperty(JEditorPane.W3C_LENGTH_UNITS, Boolean.TRUE); + } + + HTMLEditorKit kit = new HTMLEditorKit(); + htmlPane.setEditorKit(kit); + + StyleSheet styleSheet = kit.getStyleSheet(); + styleSheet.addRule("body { font-family: sans-serif; font-size: 16pt; }"); + + Document doc = kit.createDefaultDocument(); + htmlPane.setDocument(doc); + htmlPane.setText(HTML_TEXT); + + if (showFrame) { + JFrame frame = new JFrame("HtmlFontSizeGUITest: " + + (w3cUnits ? "w3c" : "std")); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.add(new JScrollPane(htmlPane), BorderLayout.CENTER); + frame.setLocationRelativeTo(null); + frame.pack(); + frame.setVisible(true); + } + + // Ignore the result but perform layout + htmlPane.getPreferredSize(); + + return htmlPane; + } + + public static void main(String[] args) throws Exception { + final List argsList = Arrays.asList(args); + final boolean showFrame = toShowFrame(argsList); + final boolean debugPrint = toDebugPrint(argsList); + + final List exceptions = new ArrayList<>(2); + SwingUtilities.invokeAndWait(() -> { + for (boolean w3cUnits : new boolean[] {true, false}) { + JEditorPane htmlPane = createEditorPane(w3cUnits, showFrame); + try { + checkFontSize(htmlPane, w3cUnits, debugPrint); + } catch (Exception e) { + exceptions.add(e); + } + } + }); + if (exceptions.size() > 0) { + exceptions.forEach(System.err::println); + throw new RuntimeException( + "Test failed: " + exceptions.get(0).getMessage(), + exceptions.get(0)); + } + } + + private static boolean toShowFrame(final List argsList) { + return argsList.contains("-show"); + } + + private static boolean toDebugPrint(final List argsList) { + return argsList.contains("-print"); + } + + private static void checkFontSize(JEditorPane htmlPane, + boolean w3cUnits, + boolean debugPrint) { + final View rootView = htmlPane.getUI().getRootView(htmlPane); + final View boxView = rootView.getView(0); + final View bodyView = boxView.getView(1); + + int fontSizePercentage = getViewFontSize(bodyView.getView(0), debugPrint); + int fontSizeInherited = getViewFontSize(bodyView.getView(1), debugPrint); + int fontSizeExplicit = getViewFontSize(bodyView.getView(2), debugPrint); + if (debugPrint) { + System.out.println("w3cUnits: " + w3cUnits + "\n" + + "Percentage: " + fontSizePercentage + "\n" + + "Inherited: " + fontSizeInherited + "\n" + + "Explicit: " + fontSizeExplicit + "\n"); + } + if (fontSizeInherited != fontSizeExplicit + || fontSizePercentage != fontSizeExplicit) { + throw new RuntimeException("The font size is different with " + + (w3cUnits ? "w3cUnits" : "stdUnits") + ": " + + "Percentage: " + fontSizePercentage + " vs. " + + "Inherited: " + fontSizeInherited + " vs. " + + "Explicit: " + fontSizeExplicit); + } + } + + private static int getViewFontSize(View paragraphView, boolean debugPrint) { + GlyphView inlineView = findFirstTextRun(paragraphView); + int fontSize = inlineView.getFont().getSize(); + if (debugPrint) { + ((AbstractElement) inlineView.getElement()).dump(System.out, 1); + } + return fontSize; + } + + private static GlyphView findFirstTextRun(View view) { + if (view instanceof GlyphView) { + return (GlyphView) view; + } + for (int i = 0; i < view.getViewCount(); i++) { + GlyphView textRun = findFirstTextRun(view.getView(i)); + if (textRun != null) { + return textRun; + } + } + return null; + } +} diff --git a/test/jdk/javax/swing/text/html/StyleSheet/TestWrongCSSFontSize.java b/test/jdk/javax/swing/text/html/StyleSheet/TestWrongCSSFontSize.java index b1fadc2d621..4c289cdcf2b 100644 --- a/test/jdk/javax/swing/text/html/StyleSheet/TestWrongCSSFontSize.java +++ b/test/jdk/javax/swing/text/html/StyleSheet/TestWrongCSSFontSize.java @@ -26,6 +26,7 @@ import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; +import java.util.Arrays; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import javax.imageio.ImageIO; @@ -39,10 +40,11 @@ * @bug 8257664 * @summary Tests inherited font-size with parent percentage specification. * @run main TestWrongCSSFontSize + * @run main TestWrongCSSFontSize -w3cUnits */ public class TestWrongCSSFontSize { - private static String text = + private static final String TEXT = "