diff --git a/.hgtags b/.hgtags index 9d9472b8350..7e800d319d4 100644 --- a/.hgtags +++ b/.hgtags @@ -650,3 +650,7 @@ f143729ca00ec14a98ea5c7f73acba88da97746e jdk-15+23 bcbe7b8a77b8971bc221c0be1bd2abb6fb68c2d0 jdk-16+2 b58fc60580550a4a587cab729d8fd87223ad6932 jdk-15+29 76810b3a88c8c641ae3850a8dfd7c40c984aea9d jdk-16+3 +6909e4a1f25bfe9a2727026f5845fc1fc44a36aa jdk-15+30 +78c07dd7240412e60d8694e9dbfd46e57bd42ee0 jdk-16+4 +78c07dd7240412e60d8694e9dbfd46e57bd42ee0 jdk-16+4 +e2622818f0bd30e736252eba101fe7d2c27f400b jdk-16+4 diff --git a/make/CompileDemos.gmk b/make/CompileDemos.gmk index 65105f14adf..f6a512703e6 100644 --- a/make/CompileDemos.gmk +++ b/make/CompileDemos.gmk @@ -52,7 +52,6 @@ TARGETS = # READMEs and other files. DEMO_SHARE_SRC := $(TOPDIR)/src/demo/share -GLOBAL_VERSION_INFO_RESOURCE := $(TOPDIR)/src/java.base/windows/native/common/version.rc DEMO_MANIFEST := $(SUPPORT_OUTPUTDIR)/demos/java-main-manifest.mf diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk index a3abaec803c..5b9d1bb1294 100644 --- a/make/CompileJavaModules.gmk +++ b/make/CompileJavaModules.gmk @@ -477,6 +477,7 @@ jdk.internal.vm.compiler_EXCLUDES += \ org.graalvm.compiler.options.test \ org.graalvm.compiler.phases.common.test \ org.graalvm.compiler.processor \ + org.graalvm.compiler.replacements.jdk10.test \ org.graalvm.compiler.replacements.jdk12.test \ org.graalvm.compiler.replacements.jdk9.test \ org.graalvm.compiler.replacements.processor \ diff --git a/make/Main.gmk b/make/Main.gmk index a3077022d35..57e86a140a6 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -640,6 +640,20 @@ $(eval $(call SetupTarget, test-image-jdk-jtreg-native, \ DEPS := build-test-jdk-jtreg-native, \ )) +# Native files needed by the testlib +$(eval $(call SetupTarget, build-test-lib-native, \ + MAKEFILE := test/BuildTestLibNative, \ + TARGET := build-test-lib-native, \ + DEPS := buildtools-jdk java.base-libs, \ +)) + +$(eval $(call SetupTarget, test-image-lib-native, \ + MAKEFILE := test/BuildTestLibNative, \ + TARGET := test-image-lib-native, \ + DEPS := build-test-lib-native, \ +)) + +# Native files needed when testing the testlib itself $(eval $(call SetupTarget, build-test-libtest-jtreg-native, \ MAKEFILE := test/JtregNativeLibTest, \ TARGET := build-test-libtest-jtreg-native, \ @@ -1118,7 +1132,9 @@ endif docs-image: docs-jdk # This target builds the test image -test-image: prepare-test-image test-image-jdk-jtreg-native test-image-demos-jdk test-image-libtest-jtreg-native +test-image: prepare-test-image test-image-jdk-jtreg-native \ + test-image-demos-jdk test-image-libtest-jtreg-native \ + test-image-lib-native ifneq ($(JVM_TEST_IMAGE_TARGETS), ) # If JVM_TEST_IMAGE_TARGETS is externally defined, use it instead of the diff --git a/make/autoconf/flags-other.m4 b/make/autoconf/flags-other.m4 index a27bde453c8..d065be82af0 100644 --- a/make/autoconf/flags-other.m4 +++ b/make/autoconf/flags-other.m4 @@ -64,39 +64,12 @@ AC_DEFUN([FLAGS_SETUP_RCFLAGS], [ # On Windows, we need to set RC flags. if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then - RC_FLAGS="-nologo -l0x409" - JVM_RCFLAGS="-nologo" + RCFLAGS="-nologo" if test "x$DEBUG_LEVEL" = xrelease; then - RC_FLAGS="$RC_FLAGS -DNDEBUG" - JVM_RCFLAGS="$JVM_RCFLAGS -DNDEBUG" + RCFLAGS="$RCFLAGS -DNDEBUG" fi - - # The version variables used to create RC_FLAGS may be overridden - # in a custom configure script, or possibly the command line. - # Let those variables be expanded at make time in spec.gmk. - # The \$ are escaped to the shell, and the $(...) variables - # are evaluated by make. - RC_FLAGS="$RC_FLAGS \ - -D\"JDK_VERSION_STRING=\$(VERSION_STRING)\" \ - -D\"JDK_COMPANY=\$(COMPANY_NAME)\" \ - -D\"JDK_FILEDESC=\$(JDK_RC_NAME) binary\" \ - -D\"JDK_VER=\$(VERSION_NUMBER)\" \ - -D\"JDK_COPYRIGHT=Copyright \xA9 $COPYRIGHT_YEAR\" \ - -D\"JDK_NAME=\$(JDK_RC_NAME) \$(VERSION_FEATURE)\" \ - -D\"JDK_FVER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\"" - - JVM_RCFLAGS="$JVM_RCFLAGS \ - -D\"HS_VERSION_STRING=\$(VERSION_STRING)\" \ - -D\"HS_COMPANY=\$(COMPANY_NAME)\" \ - -D\"HS_VER=\$(VERSION_NUMBER_FOUR_POSITIONS)\" \ - -D\"HS_INTERNAL_NAME=jvm\" \ - -D\"HS_COPYRIGHT=Copyright $COPYRIGHT_YEAR\" \ - -D\"HS_FNAME=jvm.dll\" \ - -D\"HS_NAME=\$(PRODUCT_NAME) \$(VERSION_SHORT)\" \ - -D\"HS_FVER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\"" fi - AC_SUBST(RC_FLAGS) - AC_SUBST(JVM_RCFLAGS) + AC_SUBST(RCFLAGS) ]) ################################################################################ diff --git a/make/autoconf/lib-ffi.m4 b/make/autoconf/lib-ffi.m4 index f30ed69fa0f..6aec7bc3bd2 100644 --- a/make/autoconf/lib-ffi.m4 +++ b/make/autoconf/lib-ffi.m4 @@ -87,6 +87,20 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBFFI], [LIBFFI_FOUND=no] ) fi + # on macos we need a special case for system's libffi as + # headers are located only in sdk in $SYSROOT and in ffi subfolder + if test "x$LIBFFI_FOUND" = xno; then + if test "x$SYSROOT" != "x"; then + AC_CHECK_HEADER([$SYSROOT/usr/include/ffi/ffi.h], + [ + LIBFFI_FOUND=yes + LIBFFI_CFLAGS="-I${SYSROOT}/usr/include/ffi" + LIBFFI_LIBS=-lffi + ], + [LIBFFI_FOUND=no] + ) + fi + fi if test "x$LIBFFI_FOUND" = xno; then HELP_MSG_MISSING_DEPENDENCY([ffi]) AC_MSG_ERROR([Could not find libffi! $HELP_MSG]) diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index 380caeebd88..e8cd2e69f11 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -494,7 +494,6 @@ JVM_CFLAGS := @JVM_CFLAGS@ JVM_LDFLAGS := @JVM_LDFLAGS@ JVM_ASFLAGS := @JVM_ASFLAGS@ JVM_LIBS := @JVM_LIBS@ -JVM_RCFLAGS := @JVM_RCFLAGS@ # These flags might contain variables set by a custom extension that is included later. EXTRA_CFLAGS = @EXTRA_CFLAGS@ @@ -665,12 +664,7 @@ NEW_JAVADOC = $(INTERIM_LANGTOOLS_ARGS) $(JAVADOC_MAIN_CLASS) JLINK_KEEP_PACKAGED_MODULES:=@JLINK_KEEP_PACKAGED_MODULES@ -# Base flags for RC -# Guarding this against resetting value. Legacy make files include spec multiple -# times. -ifndef RC_FLAGS - RC_FLAGS:=@RC_FLAGS@ -endif +RCFLAGS := @RCFLAGS@ # Tools adhering to a minimal and common standard of posix compliance. AWK:=@AWK@ diff --git a/make/autoconf/util_windows.m4 b/make/autoconf/util_windows.m4 index 5ccc6e93e7b..27854978cc1 100644 --- a/make/autoconf/util_windows.m4 +++ b/make/autoconf/util_windows.m4 @@ -58,7 +58,7 @@ AC_DEFUN([UTIL_REWRITE_AS_WINDOWS_MIXED_PATH], base=`basename "$unix_path"` windows_path=`$WSLPATH -m "$dir"`/"$base" if test $? -ne 0; then - AC_MSG_ERROR([Cannot convert \"$unix_path\" to Windows path]) + AC_MSG_ERROR([Cannot convert "$unix_path" to Windows path]) fi fi $1="$windows_path" diff --git a/make/common/JdkNativeCompilation.gmk b/make/common/JdkNativeCompilation.gmk index 6bb2a32a5c0..21134966dc0 100644 --- a/make/common/JdkNativeCompilation.gmk +++ b/make/common/JdkNativeCompilation.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -92,6 +92,16 @@ ProcessDir = \ ) \ ) +GLOBAL_VERSION_INFO_RESOURCE := $(TOPDIR)/src/java.base/windows/native/common/version.rc + +JDK_RCFLAGS=$(RCFLAGS) \ + -D"JDK_VERSION_STRING=$(VERSION_STRING)" \ + -D"JDK_COMPANY=$(COMPANY_NAME)" \ + -D"JDK_VER=$(VERSION_NUMBER_FOUR_POSITIONS)" \ + -D"JDK_COPYRIGHT=Copyright \xA9 $(COPYRIGHT_YEAR)" \ + -D"JDK_NAME=$(JDK_RC_NAME) $(VERSION_SHORT)" \ + -D"JDK_FVER=$(subst .,$(COMMA),$(VERSION_NUMBER_FOUR_POSITIONS))" + # Setup make rules for creating a native shared library with suitable defaults # for the OpenJDK project. # @@ -100,7 +110,7 @@ ProcessDir = \ # # Remaining parameters are named arguments. These are all passed on to # SetupNativeCompilation, except for -# EXTRA_RC_FLAGS -- additional RC_FLAGS to append. +# EXTRA_RCFLAGS -- additional RCFLAGS to append. # EXTRA_HEADER_DIRS -- additional directories to look for headers in # EXTRA_SRC -- additional directories to look for source in # EXCLUDE_SRC_PATTERNS -- exclude source dirs matching these patterns from @@ -108,6 +118,7 @@ ProcessDir = \ # HEADERS_FROM_SRC -- if false, does not add source dirs automatically as # header include dirs. (Defaults to true.) # SRC -- this is passed on, but preprocessed to accept source dir designations +# RC_FILEDESC -- override the default FILEDESC for Windows version.rc # such as "java.base:headers". SetupJdkLibrary = $(NamedParamsMacroTemplate) define SetupJdkLibraryBody @@ -137,19 +148,20 @@ define SetupJdkLibraryBody ifeq ($$($1_VERSIONINFO_RESOURCE), ) $1_VERSIONINFO_RESOURCE := $$(GLOBAL_VERSION_INFO_RESOURCE) - else ifeq ($$($1_VERSIONINFO_RESOURCE), DISABLE) - $1_VERSIONINFO_RESOURCE := endif - ifeq ($$($1_RC_FLAGS), ) - $1_RC_FLAGS := $(RC_FLAGS) \ - -D "JDK_FNAME=$$($1_NAME).dll" \ - -D "JDK_INTERNAL_NAME=$$($1_NAME)" \ - -D "JDK_FTYPE=0x2L" - else ifeq ($$($1_RC_FLAGS), DISABLE) - $1_RC_FLAGS := + ifeq ($$($1_RC_FILEDESC), ) + $1_RC_FILEDESC := $(JDK_RC_NAME) binary endif + $1_RCFLAGS := $(JDK_RCFLAGS) \ + -D"JDK_FILEDESC=$$(strip $$($1_RC_FILEDESC))" \ + -D"JDK_FNAME=$$($1_NAME).dll" \ + -D"JDK_INTERNAL_NAME=$$($1_NAME)" \ + -D"JDK_FTYPE=0x2L" \ + -I$(TOPDIR)/src/java.base/windows/native/common \ + $$($1_EXTRA_RCFLAGS) + ifneq ($$($1_HEADERS_FROM_SRC), false) $1_SRC_HEADER_FLAGS := $$(addprefix -I, $$(wildcard $$($1_SRC))) endif @@ -171,7 +183,6 @@ define SetupJdkLibraryBody ifeq ($$($1_CFLAGS)$$($1_CXXFLAGS), ) $1_CFLAGS += $$($1_SRC_HEADER_FLAGS) $$($1_EXTRA_HEADER_FLAGS) endif - $1_RC_FLAGS += $$($1_EXTRA_RC_FLAGS) # Since we reuse the rule name ($1), all our arguments will pass through. # We lose in transparency, but gain in brevity in this call... @@ -186,7 +197,7 @@ endef # # Remaining parameters are named arguments. These are all passed on to # SetupNativeCompilation, except for -# EXTRA_RC_FLAGS -- additional RC_FLAGS to append. +# EXTRA_RCFLAGS -- additional RCFLAGS to append. SetupJdkExecutable = $(NamedParamsMacroTemplate) define SetupJdkExecutableBody $1_TYPE := EXECUTABLE @@ -201,20 +212,15 @@ define SetupJdkExecutableBody ifeq ($$($1_VERSIONINFO_RESOURCE), ) $1_VERSIONINFO_RESOURCE := $$(GLOBAL_VERSION_INFO_RESOURCE) - else ifeq ($$($1_VERSIONINFO_RESOURCE), DISABLE) - $1_VERSIONINFO_RESOURCE := - endif - - ifeq ($$($1_RC_FLAGS), ) - $1_RC_FLAGS := $(RC_FLAGS) \ - -D "JDK_FNAME=$$($1_NAME).exe" \ - -D "JDK_INTERNAL_NAME=$$($1_NAME)" \ - -D "JDK_FTYPE=0x01L" - else ifeq ($$($1_RC_FLAGS), DISABLE) - $1_RC_FLAGS := endif - $1_RC_FLAGS += $$($1_EXTRA_RC_FLAGS) + $1_RCFLAGS := $(JDK_RCFLAGS) \ + -D"JDK_FILEDESC=$(JDK_RC_NAME) binary" \ + -D"JDK_FNAME=$$($1_NAME).exe" \ + -D"JDK_INTERNAL_NAME=$$($1_NAME)" \ + -D"JDK_FTYPE=0x1L" \ + -I$(TOPDIR)/src/java.base/windows/native/common \ + $$($1_EXTRA_RCFLAGS) # Since we reuse the rule name ($1), all our arguments will pass through. # We lose in transparency, but gain in brevity in this call... diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk index 9f6dff6cef9..daffb1ed5b7 100644 --- a/make/common/Modules.gmk +++ b/make/common/Modules.gmk @@ -346,6 +346,7 @@ $(MODULE_DEPS_MAKEFILE): $(MODULE_INFOS) \ sub(/\/\*.*\*\//, ""); \ gsub(/^ +\*.*/, ""); \ gsub(/ /, ""); \ + gsub(/\r/, ""); \ printf(" %s", $$0) } \ END { printf("\n") }' $m && \ $(PRINTF) "TRANSITIVE_MODULES_$(call GetModuleNameFromModuleInfo, $m) :=" && \ @@ -359,6 +360,7 @@ $(MODULE_DEPS_MAKEFILE): $(MODULE_INFOS) \ sub(/\/\*.*\*\//, ""); \ gsub(/^ +\*.*/, ""); \ gsub(/ /, ""); \ + gsub(/\r/, ""); \ printf(" %s", $$0) } \ END { printf("\n") }' $m \ ) >> $@ $(NEWLINE)) diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index c0978ffa84f..ded7fdf8c59 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -457,7 +457,7 @@ endef # EXTRA_OBJECT_FILES List of extra object files to include when linking # EXTRA_DEPS List of extra dependencies to be added to each compiled file # VERSIONINFO_RESOURCE Input file for RC. Setting this implies that RC will be run -# RC_FLAGS flags for RC. +# RCFLAGS flags for RC. # EMBED_MANIFEST if true, embed manifest on Windows. # MAPFILE mapfile # USE_MAPFILE_FOR_SYMBOLS if true and this is a STATIC_BUILD, just copy the @@ -860,7 +860,7 @@ define SetupNativeCompilationBody -include $$($1_RES_DEPS_FILE) -include $$($1_RES_DEPS_TARGETS_FILE) - $1_RES_VARDEPS := $$($1_RC) $$($1_RC_FLAGS) + $1_RES_VARDEPS := $$($1_RC) $$($1_RCFLAGS) $1_RES_VARDEPS_FILE := $$(call DependOnVariable, $1_RES_VARDEPS, \ $$($1_RES).vardeps) @@ -868,7 +868,7 @@ define SetupNativeCompilationBody $$(call LogInfo, Compiling resource $$(notdir $$($1_VERSIONINFO_RESOURCE)) (for $$($1_BASENAME))) $$(call MakeDir, $$(@D) $$($1_OBJECT_DIR)) $$(call ExecuteWithLog, $$@, $$(call MakeCommandRelative, \ - $$($1_RC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) $(CC_OUT_OPTION)$$@ \ + $$($1_RC) $$($1_RCFLAGS) $$($1_SYSROOT_CFLAGS) $(CC_OUT_OPTION)$$@ \ $$($1_VERSIONINFO_RESOURCE) 2>&1 )) # Windows RC compiler does not support -showIncludes, so we mis-use CL # for this. Filter out RC specific arguments that are unknown to CL. @@ -876,7 +876,7 @@ define SetupNativeCompilationBody # includes to stderr so need to redirect it to hide the output from the # main log. $$(call ExecuteWithLog, $$($1_RES_DEPS_FILE).obj, \ - $$($1_CC) $$(filter-out -l%, $$($1_RC_FLAGS)) \ + $$($1_CC) $$(filter-out -l%, $$($1_RCFLAGS)) \ $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \ $(CC_OUT_OPTION)$$($1_RES_DEPS_FILE).obj -P -Fi$$($1_RES_DEPS_FILE).pp \ $$($1_VERSIONINFO_RESOURCE)) 2>&1 \ diff --git a/make/common/modules/LauncherCommon.gmk b/make/common/modules/LauncherCommon.gmk index 5aa8bce79bb..c33a16a2004 100644 --- a/make/common/modules/LauncherCommon.gmk +++ b/make/common/modules/LauncherCommon.gmk @@ -48,7 +48,6 @@ LAUNCHER_CFLAGS += -I$(TOPDIR)/src/java.base/share/native/launcher \ -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli \ -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libjli \ # -GLOBAL_VERSION_INFO_RESOURCE := $(TOPDIR)/src/java.base/windows/native/common/version.rc MACOSX_PLIST_DIR := $(TOPDIR)/src/java.base/macosx/native/launcher JAVA_MANIFEST := $(TOPDIR)/src/java.base/windows/native/launcher/java.manifest @@ -71,7 +70,7 @@ JAVA_MANIFEST := $(TOPDIR)/src/java.base/windows/native/launcher/java.manifest # compile time defines exceeding Visual Studio 2013 limitations. # CFLAGS Additional CFLAGS # CFLAGS_windows Additional CFLAGS_windows -# EXTRA_RC_FLAGS Additional EXTRA_RC_FLAGS +# EXTRA_RCFLAGS Additional EXTRA_RCFLAGS # MACOSX_PRIVILEGED On macosx, allow to access other processes # OPTIMIZATION Override default optimization level (LOW) # OUTPUT_DIR Override default output directory @@ -160,7 +159,7 @@ define SetupBuildLauncherBody $(SUPPORT_OUTPUTDIR)/native/java.base/libjava/java.lib, \ OUTPUT_DIR := $$($1_OUTPUT_DIR), \ VERSIONINFO_RESOURCE := $$($1_VERSION_INFO_RESOURCE), \ - EXTRA_RC_FLAGS := $$($1_EXTRA_RC_FLAGS), \ + EXTRA_RCFLAGS := $$($1_EXTRA_RCFLAGS), \ MANIFEST := $(JAVA_MANIFEST), \ MANIFEST_VERSION := $(VERSION_NUMBER_FOUR_POSITIONS), \ )) diff --git a/make/common/modules/LibCommon.gmk b/make/common/modules/LibCommon.gmk index f841ad9b166..8ca3ddfffe9 100644 --- a/make/common/modules/LibCommon.gmk +++ b/make/common/modules/LibCommon.gmk @@ -27,8 +27,6 @@ include JdkNativeCompilation.gmk ################################################################################ -GLOBAL_VERSION_INFO_RESOURCE := $(TOPDIR)/src/java.base/windows/native/common/version.rc - # Absolute paths to lib files on windows for use in LIBS. Should figure out a more # elegant solution to this. WIN_JAVA_LIB := $(SUPPORT_OUTPUTDIR)/native/java.base/libjava/java.lib diff --git a/make/data/symbols/java.base-7.sym.txt b/make/data/symbols/java.base-7.sym.txt index a3f31688497..5d8369f74cb 100644 --- a/make/data/symbols/java.base-7.sym.txt +++ b/make/data/symbols/java.base-7.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -632,10 +632,37 @@ class name java/security/cert/X509CRL class name java/security/cert/X509Certificate -method name verify descriptor (Ljava/security/PublicKey;Ljava/security/Provider;)V +class name java/security/interfaces/RSAKey +-method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; + -class name java/security/spec/DSAGenParameterSpec class name java/security/spec/MGF1ParameterSpec -field name SHA224 descriptor Ljava/security/spec/MGF1ParameterSpec; +-field name SHA512_224 descriptor Ljava/security/spec/MGF1ParameterSpec; +-field name SHA512_256 descriptor Ljava/security/spec/MGF1ParameterSpec; + +class name java/security/spec/PSSParameterSpec +-field name TRAILER_FIELD_BC descriptor I +-method name toString descriptor ()Ljava/lang/String; + +class name java/security/spec/RSAKeyGenParameterSpec +-method name descriptor (ILjava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V +-method name getKeyParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; + +class name java/security/spec/RSAMultiPrimePrivateCrtKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;[Ljava/security/spec/RSAOtherPrimeInfo;Ljava/security/spec/AlgorithmParameterSpec;)V + +class name java/security/spec/RSAPrivateCrtKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V + +class name java/security/spec/RSAPrivateKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V +-method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; + +class name java/security/spec/RSAPublicKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V +-method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; class name java/text/Collator -method name getInstance descriptor (Ljava/util/Locale;)Ljava/text/Collator; @@ -1457,6 +1484,14 @@ method name newUpdater descriptor (Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/ -class name java/util/function/UnaryOperator +class name java/util/jar/Attributes$Name +-field name EXTENSION_INSTALLATION descriptor Ljava/util/jar/Attributes$Name; +-field name IMPLEMENTATION_VENDOR_ID descriptor Ljava/util/jar/Attributes$Name; +-field name IMPLEMENTATION_URL descriptor Ljava/util/jar/Attributes$Name; +field name EXTENSION_INSTALLATION descriptor Ljava/util/jar/Attributes$Name; flags 19 +field name IMPLEMENTATION_VENDOR_ID descriptor Ljava/util/jar/Attributes$Name; flags 19 +field name IMPLEMENTATION_URL descriptor Ljava/util/jar/Attributes$Name; flags 19 + class name java/util/jar/JarFile -method name stream descriptor ()Ljava/util/stream/Stream; @@ -1535,6 +1570,9 @@ class name java/util/zip/ZipEntry class name java/util/zip/ZipFile -method name stream descriptor ()Ljava/util/stream/Stream; +class name javax/crypto/SealedObject +header extends java/lang/Object implements java/io/Serializable flags 21 + class name javax/crypto/SecretKey header extends java/lang/Object implements java/security/Key flags 601 @@ -1559,6 +1597,12 @@ class name javax/net/ssl/ExtendedSSLSession -class name javax/net/ssl/SNIServerName +class name javax/net/ssl/SSLEngine +-method name getApplicationProtocol descriptor ()Ljava/lang/String; +-method name getHandshakeApplicationProtocol descriptor ()Ljava/lang/String; +-method name setHandshakeApplicationProtocolSelector descriptor (Ljava/util/function/BiFunction;)V +-method name getHandshakeApplicationProtocolSelector descriptor ()Ljava/util/function/BiFunction; + class name javax/net/ssl/SSLParameters -method name setServerNames descriptor (Ljava/util/List;)V -method name getServerNames descriptor ()Ljava/util/List; @@ -1566,6 +1610,14 @@ class name javax/net/ssl/SSLParameters -method name getSNIMatchers descriptor ()Ljava/util/Collection; -method name setUseCipherSuitesOrder descriptor (Z)V -method name getUseCipherSuitesOrder descriptor ()Z +-method name getApplicationProtocols descriptor ()[Ljava/lang/String; +-method name setApplicationProtocols descriptor ([Ljava/lang/String;)V + +class name javax/net/ssl/SSLSocket +-method name getApplicationProtocol descriptor ()Ljava/lang/String; +-method name getHandshakeApplicationProtocol descriptor ()Ljava/lang/String; +-method name setHandshakeApplicationProtocolSelector descriptor (Ljava/util/function/BiFunction;)V +-method name getHandshakeApplicationProtocolSelector descriptor ()Ljava/util/function/BiFunction; class name javax/net/ssl/SSLSocketFactory -method name createSocket descriptor (Ljava/net/Socket;Ljava/io/InputStream;Z)Ljava/net/Socket; diff --git a/make/data/symbols/java.base-8.sym.txt b/make/data/symbols/java.base-8.sym.txt index 5f3cc3e082c..051003c2799 100644 --- a/make/data/symbols/java.base-8.sym.txt +++ b/make/data/symbols/java.base-8.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -8200,6 +8200,7 @@ method name getW descriptor ()Ljava/security/spec/ECPoint; flags 401 class name java/security/interfaces/RSAKey header extends java/lang/Object flags 601 classAnnotations @Ljdk/Profile+Annotation;(value=I1) method name getModulus descriptor ()Ljava/math/BigInteger; flags 401 +method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; flags 1 class name java/security/interfaces/RSAMultiPrimePrivateCrtKey header extends java/lang/Object implements java/security/interfaces/RSAPrivateKey flags 601 classAnnotations @Ljdk/Profile+Annotation;(value=I1) @@ -8363,6 +8364,8 @@ field name SHA224 descriptor Ljava/security/spec/MGF1ParameterSpec; flags 19 field name SHA256 descriptor Ljava/security/spec/MGF1ParameterSpec; flags 19 field name SHA384 descriptor Ljava/security/spec/MGF1ParameterSpec; flags 19 field name SHA512 descriptor Ljava/security/spec/MGF1ParameterSpec; flags 19 +field name SHA512_224 descriptor Ljava/security/spec/MGF1ParameterSpec; flags 19 +field name SHA512_256 descriptor Ljava/security/spec/MGF1ParameterSpec; flags 19 method name descriptor (Ljava/lang/String;)V flags 1 method name getDigestAlgorithm descriptor ()Ljava/lang/String; flags 1 @@ -8375,6 +8378,7 @@ method name getFormat descriptor ()Ljava/lang/String; flags 11 class name java/security/spec/PSSParameterSpec header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) field name DEFAULT descriptor Ljava/security/spec/PSSParameterSpec; flags 19 +field name TRAILER_FIELD_BC descriptor I constantValue 1 flags 19 method name descriptor (Ljava/lang/String;Ljava/lang/String;Ljava/security/spec/AlgorithmParameterSpec;II)V flags 1 method name descriptor (I)V flags 1 method name getDigestAlgorithm descriptor ()Ljava/lang/String; flags 1 @@ -8382,6 +8386,7 @@ method name getMGFAlgorithm descriptor ()Ljava/lang/String; flags 1 method name getMGFParameters descriptor ()Ljava/security/spec/AlgorithmParameterSpec; flags 1 method name getSaltLength descriptor ()I flags 1 method name getTrailerField descriptor ()I flags 1 +method name toString descriptor ()Ljava/lang/String; flags 1 class name java/security/spec/RSAKeyGenParameterSpec header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) @@ -8390,6 +8395,8 @@ field name F4 descriptor Ljava/math/BigInteger; flags 19 method name descriptor (ILjava/math/BigInteger;)V flags 1 method name getKeysize descriptor ()I flags 1 method name getPublicExponent descriptor ()Ljava/math/BigInteger; flags 1 +method name descriptor (ILjava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 +method name getKeyParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; flags 1 class name java/security/spec/RSAMultiPrimePrivateCrtKeySpec header extends java/security/spec/RSAPrivateKeySpec flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) @@ -8401,6 +8408,7 @@ method name getPrimeExponentP descriptor ()Ljava/math/BigInteger; flags 1 method name getPrimeExponentQ descriptor ()Ljava/math/BigInteger; flags 1 method name getCrtCoefficient descriptor ()Ljava/math/BigInteger; flags 1 method name getOtherPrimeInfo descriptor ()[Ljava/security/spec/RSAOtherPrimeInfo; flags 1 +method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;[Ljava/security/spec/RSAOtherPrimeInfo;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 class name java/security/spec/RSAOtherPrimeInfo header extends java/lang/Object flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) @@ -8418,18 +8426,23 @@ method name getPrimeQ descriptor ()Ljava/math/BigInteger; flags 1 method name getPrimeExponentP descriptor ()Ljava/math/BigInteger; flags 1 method name getPrimeExponentQ descriptor ()Ljava/math/BigInteger; flags 1 method name getCrtCoefficient descriptor ()Ljava/math/BigInteger; flags 1 +method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 class name java/security/spec/RSAPrivateKeySpec header extends java/lang/Object implements java/security/spec/KeySpec flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;)V flags 1 method name getModulus descriptor ()Ljava/math/BigInteger; flags 1 method name getPrivateExponent descriptor ()Ljava/math/BigInteger; flags 1 +method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 +method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; flags 1 class name java/security/spec/RSAPublicKeySpec header extends java/lang/Object implements java/security/spec/KeySpec flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;)V flags 1 method name getModulus descriptor ()Ljava/math/BigInteger; flags 1 method name getPublicExponent descriptor ()Ljava/math/BigInteger; flags 1 +method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 +method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; flags 1 class name java/security/spec/X509EncodedKeySpec header extends java/security/spec/EncodedKeySpec flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) @@ -10429,6 +10442,7 @@ method name values descriptor ()[Ljava/time/chrono/JapaneseEra; flags 9 method name getValue descriptor ()I flags 1 method name range descriptor (Ljava/time/temporal/TemporalField;)Ljava/time/temporal/ValueRange; flags 1 method name toString descriptor ()Ljava/lang/String; flags 1 +method name getDisplayName descriptor (Ljava/time/format/TextStyle;Ljava/util/Locale;)Ljava/lang/String; flags 1 class name java/time/chrono/MinguoChronology header extends java/time/chrono/AbstractChronology implements java/io/Serializable flags 31 classAnnotations @Ljdk/Profile+Annotation;(value=I1) @@ -15563,15 +15577,15 @@ field name MAIN_CLASS descriptor Ljava/util/jar/Attributes$Name; flags 19 field name SEALED descriptor Ljava/util/jar/Attributes$Name; flags 19 field name EXTENSION_LIST descriptor Ljava/util/jar/Attributes$Name; flags 19 field name EXTENSION_NAME descriptor Ljava/util/jar/Attributes$Name; flags 19 -field name EXTENSION_INSTALLATION descriptor Ljava/util/jar/Attributes$Name; flags 19 field name IMPLEMENTATION_TITLE descriptor Ljava/util/jar/Attributes$Name; flags 19 field name IMPLEMENTATION_VERSION descriptor Ljava/util/jar/Attributes$Name; flags 19 field name IMPLEMENTATION_VENDOR descriptor Ljava/util/jar/Attributes$Name; flags 19 -field name IMPLEMENTATION_VENDOR_ID descriptor Ljava/util/jar/Attributes$Name; flags 19 -field name IMPLEMENTATION_URL descriptor Ljava/util/jar/Attributes$Name; flags 19 field name SPECIFICATION_TITLE descriptor Ljava/util/jar/Attributes$Name; flags 19 field name SPECIFICATION_VERSION descriptor Ljava/util/jar/Attributes$Name; flags 19 field name SPECIFICATION_VENDOR descriptor Ljava/util/jar/Attributes$Name; flags 19 +field name EXTENSION_INSTALLATION descriptor Ljava/util/jar/Attributes$Name; flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; +field name IMPLEMENTATION_VENDOR_ID descriptor Ljava/util/jar/Attributes$Name; flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; +field name IMPLEMENTATION_URL descriptor Ljava/util/jar/Attributes$Name; flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; method name descriptor (Ljava/lang/String;)V flags 1 method name equals descriptor (Ljava/lang/Object;)Z flags 1 method name hashCode descriptor ()I flags 1 @@ -16698,6 +16712,7 @@ method name descriptor ()V flags 1 class name javax/crypto/SealedObject header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 field name encodedParams descriptor [B flags 4 method name descriptor (Ljava/io/Serializable;Ljavax/crypto/Cipher;)V thrownTypes java/io/IOException,javax/crypto/IllegalBlockSizeException flags 1 method name descriptor (Ljavax/crypto/SealedObject;)V flags 4 @@ -17086,6 +17101,10 @@ method name setEnableSessionCreation descriptor (Z)V flags 401 method name getEnableSessionCreation descriptor ()Z flags 401 method name getSSLParameters descriptor ()Ljavax/net/ssl/SSLParameters; flags 1 method name setSSLParameters descriptor (Ljavax/net/ssl/SSLParameters;)V flags 1 +method name getApplicationProtocol descriptor ()Ljava/lang/String; flags 1 +method name getHandshakeApplicationProtocol descriptor ()Ljava/lang/String; flags 1 +method name setHandshakeApplicationProtocolSelector descriptor (Ljava/util/function/BiFunction;)V flags 1 signature (Ljava/util/function/BiFunction;Ljava/lang/String;>;)V +method name getHandshakeApplicationProtocolSelector descriptor ()Ljava/util/function/BiFunction; flags 1 signature ()Ljava/util/function/BiFunction;Ljava/lang/String;>; class name javax/net/ssl/SSLEngineResult header extends java/lang/Object flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) @@ -17156,6 +17175,8 @@ method name setSNIMatchers descriptor (Ljava/util/Collection;)V flags 11 signatu method name getSNIMatchers descriptor ()Ljava/util/Collection; flags 11 signature ()Ljava/util/Collection; method name setUseCipherSuitesOrder descriptor (Z)V flags 11 method name getUseCipherSuitesOrder descriptor ()Z flags 11 +method name getApplicationProtocols descriptor ()[Ljava/lang/String; flags 1 +method name setApplicationProtocols descriptor ([Ljava/lang/String;)V flags 1 class name javax/net/ssl/SSLPeerUnverifiedException header extends javax/net/ssl/SSLException flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) @@ -17272,6 +17293,10 @@ method name setEnableSessionCreation descriptor (Z)V flags 401 method name getEnableSessionCreation descriptor ()Z flags 401 method name getSSLParameters descriptor ()Ljavax/net/ssl/SSLParameters; flags 1 method name setSSLParameters descriptor (Ljavax/net/ssl/SSLParameters;)V flags 1 +method name getApplicationProtocol descriptor ()Ljava/lang/String; flags 1 +method name getHandshakeApplicationProtocol descriptor ()Ljava/lang/String; flags 1 +method name setHandshakeApplicationProtocolSelector descriptor (Ljava/util/function/BiFunction;)V flags 1 signature (Ljava/util/function/BiFunction;Ljava/lang/String;>;)V +method name getHandshakeApplicationProtocolSelector descriptor ()Ljava/util/function/BiFunction; flags 1 signature ()Ljava/util/function/BiFunction;Ljava/lang/String;>; class name javax/net/ssl/SSLSocketFactory header extends javax/net/SocketFactory flags 421 classAnnotations @Ljdk/Profile+Annotation;(value=I1) diff --git a/make/data/symbols/java.base-9.sym.txt b/make/data/symbols/java.base-9.sym.txt index bdaa9a35800..99a4f8e9f0e 100644 --- a/make/data/symbols/java.base-9.sym.txt +++ b/make/data/symbols/java.base-9.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -2083,13 +2083,42 @@ method name equals descriptor (Ljava/lang/Object;)Z flags 1 method name toString descriptor ()Ljava/lang/String; flags 1 method name clone descriptor ()Ljava/lang/Object; thrownTypes java/lang/CloneNotSupportedException flags 1041 +class name java/security/interfaces/RSAKey +-method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; + class name java/security/spec/EncodedKeySpec method name descriptor ([BLjava/lang/String;)V flags 4 method name getAlgorithm descriptor ()Ljava/lang/String; flags 1 +class name java/security/spec/MGF1ParameterSpec +-field name SHA512_224 descriptor Ljava/security/spec/MGF1ParameterSpec; +-field name SHA512_256 descriptor Ljava/security/spec/MGF1ParameterSpec; + class name java/security/spec/PKCS8EncodedKeySpec method name descriptor ([BLjava/lang/String;)V flags 1 +class name java/security/spec/PSSParameterSpec +-field name TRAILER_FIELD_BC descriptor I +-method name toString descriptor ()Ljava/lang/String; + +class name java/security/spec/RSAKeyGenParameterSpec +-method name descriptor (ILjava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V +-method name getKeyParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; + +class name java/security/spec/RSAMultiPrimePrivateCrtKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;[Ljava/security/spec/RSAOtherPrimeInfo;Ljava/security/spec/AlgorithmParameterSpec;)V + +class name java/security/spec/RSAPrivateCrtKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V + +class name java/security/spec/RSAPrivateKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V +-method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; + +class name java/security/spec/RSAPublicKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V +-method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; + class name java/security/spec/X509EncodedKeySpec method name descriptor ([BLjava/lang/String;)V flags 1 @@ -2224,9 +2253,6 @@ innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang class name java/time/chrono/IsoChronology method name epochSecond descriptor (IIIIIILjava/time/ZoneOffset;)J flags 1 -class name java/time/chrono/JapaneseEra -method name getDisplayName descriptor (Ljava/time/format/TextStyle;Ljava/util/Locale;)Ljava/lang/String; flags 1 - class name java/time/format/DateTimeFormatter header extends java/lang/Object flags 31 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 @@ -3221,12 +3247,6 @@ header extends java/lang/Object implements java/util/function/Function flags 601 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 class name java/util/jar/Attributes$Name --field name EXTENSION_INSTALLATION descriptor Ljava/util/jar/Attributes$Name; --field name IMPLEMENTATION_VENDOR_ID descriptor Ljava/util/jar/Attributes$Name; --field name IMPLEMENTATION_URL descriptor Ljava/util/jar/Attributes$Name; -field name EXTENSION_INSTALLATION descriptor Ljava/util/jar/Attributes$Name; flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; -field name IMPLEMENTATION_VENDOR_ID descriptor Ljava/util/jar/Attributes$Name; flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; -field name IMPLEMENTATION_URL descriptor Ljava/util/jar/Attributes$Name; flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; field name MULTI_RELEASE descriptor Ljava/util/jar/Attributes$Name; flags 19 class name java/util/jar/JarFile @@ -3381,6 +3401,9 @@ method name finalize descriptor ()V thrownTypes java/io/IOException flags 4 depr class name javax/crypto/ExemptionMechanism -method name finalize descriptor ()V +class name javax/crypto/SealedObject +header extends java/lang/Object implements java/io/Serializable flags 21 + class name javax/net/ssl/ExtendedSSLSession method name getStatusResponses descriptor ()Ljava/util/List; flags 1 signature ()Ljava/util/List<[B>; @@ -3388,12 +3411,6 @@ class name javax/net/ssl/HandshakeCompletedEvent -method name getPeerCertificateChain descriptor ()[Ljavax/security/cert/X509Certificate; method name getPeerCertificateChain descriptor ()[Ljavax/security/cert/X509Certificate; thrownTypes javax/net/ssl/SSLPeerUnverifiedException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") -class name javax/net/ssl/SSLEngine -method name getApplicationProtocol descriptor ()Ljava/lang/String; flags 1 -method name getHandshakeApplicationProtocol descriptor ()Ljava/lang/String; flags 1 -method name setHandshakeApplicationProtocolSelector descriptor (Ljava/util/function/BiFunction;)V flags 1 signature (Ljava/util/function/BiFunction;Ljava/lang/String;>;)V -method name getHandshakeApplicationProtocolSelector descriptor ()Ljava/util/function/BiFunction; flags 1 signature ()Ljava/util/function/BiFunction;Ljava/lang/String;>; - class name javax/net/ssl/SSLEngineResult header extends java/lang/Object flags 21 innerclass innerClass javax/net/ssl/SSLEngineResult$HandshakeStatus outerClass javax/net/ssl/SSLEngineResult innerClassName HandshakeStatus flags 4019 @@ -3409,19 +3426,11 @@ method name setEnableRetransmissions descriptor (Z)V flags 1 method name getEnableRetransmissions descriptor ()Z flags 1 method name setMaximumPacketSize descriptor (I)V flags 1 method name getMaximumPacketSize descriptor ()I flags 1 -method name getApplicationProtocols descriptor ()[Ljava/lang/String; flags 1 -method name setApplicationProtocols descriptor ([Ljava/lang/String;)V flags 1 class name javax/net/ssl/SSLSession -method name getPeerCertificateChain descriptor ()[Ljavax/security/cert/X509Certificate; method name getPeerCertificateChain descriptor ()[Ljavax/security/cert/X509Certificate; thrownTypes javax/net/ssl/SSLPeerUnverifiedException flags 401 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") -class name javax/net/ssl/SSLSocket -method name getApplicationProtocol descriptor ()Ljava/lang/String; flags 1 -method name getHandshakeApplicationProtocol descriptor ()Ljava/lang/String; flags 1 -method name setHandshakeApplicationProtocolSelector descriptor (Ljava/util/function/BiFunction;)V flags 1 signature (Ljava/util/function/BiFunction;Ljava/lang/String;>;)V -method name getHandshakeApplicationProtocolSelector descriptor ()Ljava/util/function/BiFunction; flags 1 signature ()Ljava/util/function/BiFunction;Ljava/lang/String;>; - class name javax/security/auth/Policy header extends java/lang/Object flags 421 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.4") diff --git a/make/data/symbols/java.base-F.sym.txt b/make/data/symbols/java.base-F.sym.txt index 9054ae35c77..a089d45bf39 100644 --- a/make/data/symbols/java.base-F.sym.txt +++ b/make/data/symbols/java.base-F.sym.txt @@ -182,6 +182,20 @@ class name java/nio/channels/spi/SelectorProvider method name openSocketChannel descriptor (Ljava/net/ProtocolFamily;)Ljava/nio/channels/SocketChannel; thrownTypes java/io/IOException flags 1 method name openServerSocketChannel descriptor (Ljava/net/ProtocolFamily;)Ljava/nio/channels/ServerSocketChannel; thrownTypes java/io/IOException flags 1 +class name java/security/KeyStore +header extends java/lang/Object nestMembers java/security/KeyStore$Builder,java/security/KeyStore$TrustedCertificateEntry,java/security/KeyStore$SecretKeyEntry,java/security/KeyStore$PrivateKeyEntry,java/security/KeyStore$Entry,java/security/KeyStore$Entry$Attribute,java/security/KeyStore$CallbackHandlerProtection,java/security/KeyStore$PasswordProtection,java/security/KeyStore$ProtectionParameter,java/security/KeyStore$LoadStoreParameter flags 21 +innerclass innerClass java/security/KeyStore$LoadStoreParameter outerClass java/security/KeyStore innerClassName LoadStoreParameter flags 609 +innerclass innerClass java/security/KeyStore$ProtectionParameter outerClass java/security/KeyStore innerClassName ProtectionParameter flags 609 +innerclass innerClass java/security/KeyStore$Entry outerClass java/security/KeyStore innerClassName Entry flags 609 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 +innerclass innerClass java/security/KeyStore$Builder outerClass java/security/KeyStore innerClassName Builder flags 409 +innerclass innerClass java/security/KeyStore$TrustedCertificateEntry outerClass java/security/KeyStore innerClassName TrustedCertificateEntry flags 19 +innerclass innerClass java/security/KeyStore$SecretKeyEntry outerClass java/security/KeyStore innerClassName SecretKeyEntry flags 19 +innerclass innerClass java/security/KeyStore$PrivateKeyEntry outerClass java/security/KeyStore innerClassName PrivateKeyEntry flags 19 +innerclass innerClass java/security/KeyStore$CallbackHandlerProtection outerClass java/security/KeyStore innerClassName CallbackHandlerProtection flags 9 +innerclass innerClass java/security/KeyStore$PasswordProtection outerClass java/security/KeyStore innerClassName PasswordProtection flags 9 +innerclass innerClass java/security/KeyStore$Entry$Attribute outerClass java/security/KeyStore$Entry innerClassName Attribute flags 609 + class name java/security/interfaces/EdECKey header extends java/lang/Object flags 601 method name getParams descriptor ()Ljava/security/spec/NamedParameterSpec; flags 401 diff --git a/make/data/symbols/java.desktop-7.sym.txt b/make/data/symbols/java.desktop-7.sym.txt index 131531e2b01..0163545ddd3 100644 --- a/make/data/symbols/java.desktop-7.sym.txt +++ b/make/data/symbols/java.desktop-7.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -77,6 +77,9 @@ class name javax/swing/ImageIcon field name component descriptor Ljava/awt/Component; flags 1c field name tracker descriptor Ljava/awt/MediaTracker; flags 1c +class name javax/swing/JComboBox +-method name processKeyBinding descriptor (Ljavax/swing/KeyStroke;Ljava/awt/event/KeyEvent;IZ)Z + class name javax/swing/JComponent field name accessibleContext descriptor Ljavax/accessibility/AccessibleContext; flags 4 -method name hide descriptor ()V @@ -90,8 +93,12 @@ field name accessibleFocusHandler descriptor Ljava/awt/event/FocusListener; flag class name javax/swing/JDesktopPane -method name remove descriptor (Ljava/awt/Component;)V -class name javax/swing/JViewport --method name addNotify descriptor ()V +class name javax/swing/JList$AccessibleJList$AccessibleJListChild +method name getAccessibleAction descriptor ()Ljavax/accessibility/AccessibleAction; flags 1 + +class name javax/swing/plaf/basic/BasicRadioButtonUI +-method name installListeners descriptor (Ljavax/swing/AbstractButton;)V +-method name uninstallListeners descriptor (Ljavax/swing/AbstractButton;)V class name javax/swing/tree/DefaultMutableTreeNode -method name setParent descriptor (Ljavax/swing/tree/MutableTreeNode;)V diff --git a/make/data/symbols/java.desktop-8.sym.txt b/make/data/symbols/java.desktop-8.sym.txt index 835cdde3043..3daa15e5081 100644 --- a/make/data/symbols/java.desktop-8.sym.txt +++ b/make/data/symbols/java.desktop-8.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -13524,6 +13524,7 @@ method name getItemAt descriptor (I)Ljava/lang/Object; flags 1 signature (I)TE; method name createDefaultKeySelectionManager descriptor ()Ljavax/swing/JComboBox$KeySelectionManager; flags 4 method name paramString descriptor ()Ljava/lang/String; flags 4 method name getAccessibleContext descriptor ()Ljavax/accessibility/AccessibleContext; flags 1 +method name processKeyBinding descriptor (Ljavax/swing/KeyStroke;Ljava/awt/event/KeyEvent;IZ)Z flags 4 class name javax/swing/JComboBox$AccessibleJComboBox header extends javax/swing/JComponent$AccessibleJComponent implements javax/accessibility/AccessibleAction,javax/accessibility/AccessibleSelection flags 21 @@ -14604,7 +14605,6 @@ method name getAccessibleChild descriptor (I)Ljavax/accessibility/Accessible; fl method name getLocale descriptor ()Ljava/util/Locale; flags 1 method name addPropertyChangeListener descriptor (Ljava/beans/PropertyChangeListener;)V flags 1 method name removePropertyChangeListener descriptor (Ljava/beans/PropertyChangeListener;)V flags 1 -method name getAccessibleAction descriptor ()Ljavax/accessibility/AccessibleAction; flags 1 method name getAccessibleComponent descriptor ()Ljavax/accessibility/AccessibleComponent; flags 1 method name getAccessibleSelection descriptor ()Ljavax/accessibility/AccessibleSelection; flags 1 method name getAccessibleText descriptor ()Ljavax/accessibility/AccessibleText; flags 1 @@ -16720,7 +16720,6 @@ method name updateUI descriptor ()V flags 1 method name getUIClassID descriptor ()Ljava/lang/String; flags 1 method name addImpl descriptor (Ljava/awt/Component;Ljava/lang/Object;I)V flags 4 method name remove descriptor (Ljava/awt/Component;)V flags 1 -method name addNotify descriptor ()V flags 1 method name scrollRectToVisible descriptor (Ljava/awt/Rectangle;)V flags 1 method name setBorder descriptor (Ljavax/swing/border/Border;)V flags 11 method name getInsets descriptor ()Ljava/awt/Insets; flags 11 @@ -20281,6 +20280,8 @@ method name getDefaultIcon descriptor ()Ljavax/swing/Icon; flags 1 method name paint descriptor (Ljava/awt/Graphics;Ljavax/swing/JComponent;)V flags 21 method name paintFocus descriptor (Ljava/awt/Graphics;Ljava/awt/Rectangle;Ljava/awt/Dimension;)V flags 4 method name getPreferredSize descriptor (Ljavax/swing/JComponent;)Ljava/awt/Dimension; flags 1 +method name installListeners descriptor (Ljavax/swing/AbstractButton;)V flags 4 +method name uninstallListeners descriptor (Ljavax/swing/AbstractButton;)V flags 4 class name javax/swing/plaf/basic/BasicRootPaneUI header extends javax/swing/plaf/RootPaneUI implements java/beans/PropertyChangeListener flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I4) diff --git a/make/data/symbols/java.desktop-9.sym.txt b/make/data/symbols/java.desktop-9.sym.txt index 421eb345695..cf0ab3466a8 100644 --- a/make/data/symbols/java.desktop-9.sym.txt +++ b/make/data/symbols/java.desktop-9.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -2524,7 +2524,6 @@ method name getPopupMenuListeners descriptor ()[Ljavax/swing/event/PopupMenuList method name setAction descriptor (Ljavax/swing/Action;)V flags 1 runtimeAnnotations @Ljava/beans/BeanProperty;(visualUpdate=Ztrue,description="the\u005C;u0020;Action\u005C;u0020;instance\u005C;u0020;connected\u005C;u0020;with\u005C;u0020;this\u005C;u0020;ActionEvent\u005C;u0020;source") method name getSelectedObjects descriptor ()[Ljava/lang/Object; flags 1 runtimeAnnotations @Ljava/beans/BeanProperty;(bound=Zfalse) method name setEnabled descriptor (Z)V flags 1 runtimeAnnotations @Ljava/beans/BeanProperty;(description="The\u005C;u0020;enabled\u005C;u0020;state\u005C;u0020;of\u005C;u0020;the\u005C;u0020;component.",preferred=Ztrue) -method name processKeyBinding descriptor (Ljavax/swing/KeyStroke;Ljava/awt/event/KeyEvent;IZ)Z flags 4 method name setKeySelectionManager descriptor (Ljavax/swing/JComboBox$KeySelectionManager;)V flags 1 runtimeAnnotations @Ljava/beans/BeanProperty;(expert=Ztrue,bound=Zfalse,description="The\u005C;u0020;objects\u005C;u0020;that\u005C;u0020;changes\u005C;u0020;the\u005C;u0020;selection\u005C;u0020;when\u005C;u0020;a\u005C;u0020;key\u005C;u0020;is\u005C;u0020;pressed.") method name getItemCount descriptor ()I flags 1 runtimeAnnotations @Ljava/beans/BeanProperty;(bound=Zfalse) method name getAccessibleContext descriptor ()Ljavax/accessibility/AccessibleContext; flags 1 runtimeAnnotations @Ljava/beans/BeanProperty;(bound=Zfalse) @@ -3039,6 +3038,7 @@ class name javax/swing/JList$AccessibleJList$AccessibleJListChild header extends javax/accessibility/AccessibleContext implements javax/accessibility/Accessible,javax/accessibility/AccessibleComponent,javax/accessibility/AccessibleAction flags 21 innerclass innerClass javax/swing/JList$AccessibleJList outerClass javax/swing/JList innerClassName AccessibleJList flags 4 innerclass innerClass javax/swing/JList$AccessibleJList$AccessibleJListChild outerClass javax/swing/JList$AccessibleJList innerClassName AccessibleJListChild flags 4 +method name getAccessibleAction descriptor ()Ljavax/accessibility/AccessibleAction; flags 1 method name doAccessibleAction descriptor (I)Z flags 1 method name getAccessibleActionDescription descriptor (I)Ljava/lang/String; flags 1 method name getAccessibleActionCount descriptor ()I flags 1 @@ -3907,7 +3907,6 @@ innerclass innerClass javax/swing/JViewport$AccessibleJViewport outerClass javax innerclass innerClass javax/swing/JViewport$ViewListener outerClass javax/swing/JViewport innerClassName ViewListener flags 4 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 -method name setUI descriptor (Ljavax/swing/plaf/ViewportUI;)V --method name addNotify descriptor ()V -method name getInsets descriptor (Ljava/awt/Insets;)Ljava/awt/Insets; -method name setScrollMode descriptor (I)V method name setUI descriptor (Ljavax/swing/plaf/ViewportUI;)V flags 1 runtimeAnnotations @Ljava/beans/BeanProperty;(hidden=Ztrue,visualUpdate=Ztrue,description="The\u005C;u0020;UI\u005C;u0020;object\u005C;u0020;that\u005C;u0020;implements\u005C;u0020;the\u005C;u0020;Component's\u005C;u0020;LookAndFeel.") @@ -4402,8 +4401,6 @@ innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang class name javax/swing/plaf/basic/BasicRadioButtonUI header extends javax/swing/plaf/basic/BasicToggleButtonUI flags 21 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 -method name installListeners descriptor (Ljavax/swing/AbstractButton;)V flags 4 -method name uninstallListeners descriptor (Ljavax/swing/AbstractButton;)V flags 4 class name javax/swing/plaf/basic/BasicScrollBarUI header extends javax/swing/plaf/ScrollBarUI implements java/awt/LayoutManager,javax/swing/SwingConstants flags 21 diff --git a/make/data/symbols/symbols b/make/data/symbols/symbols index 0f8120f7e25..bc500a82330 100644 --- a/make/data/symbols/symbols +++ b/make/data/symbols/symbols @@ -27,7 +27,7 @@ # ########################################################## # #command used to generate this file: -#build.tools.symbolgenerator.CreateSymbols build-description-incremental symbols include.list +#build.tools.symbolgenerator.CreateSymbols build-description-incremental-file symbols include.list 8 jdk8-updated.classes --normalize-method-flags # generate platforms 7:8:9:A:B:C:D:E:F platform version 8 files java.activation-8.sym.txt:java.base-8.sym.txt:java.compiler-8.sym.txt:java.corba-8.sym.txt:java.datatransfer-8.sym.txt:java.desktop-8.sym.txt:java.instrument-8.sym.txt:java.logging-8.sym.txt:java.management-8.sym.txt:java.management.rmi-8.sym.txt:java.naming-8.sym.txt:java.prefs-8.sym.txt:java.rmi-8.sym.txt:java.scripting-8.sym.txt:java.security.jgss-8.sym.txt:java.security.sasl-8.sym.txt:java.sql-8.sym.txt:java.sql.rowset-8.sym.txt:java.transaction-8.sym.txt:java.xml-8.sym.txt:java.xml.bind-8.sym.txt:java.xml.crypto-8.sym.txt:java.xml.ws-8.sym.txt:java.xml.ws.annotation-8.sym.txt:jdk.httpserver-8.sym.txt:jdk.management-8.sym.txt:jdk.scripting.nashorn-8.sym.txt:jdk.sctp-8.sym.txt:jdk.security.auth-8.sym.txt:jdk.security.jgss-8.sym.txt diff --git a/make/hotspot/lib/CompileJvm.gmk b/make/hotspot/lib/CompileJvm.gmk index 6f851f6f38a..8aee876ca77 100644 --- a/make/hotspot/lib/CompileJvm.gmk +++ b/make/hotspot/lib/CompileJvm.gmk @@ -124,13 +124,6 @@ else ifeq ($(call isTargetCpu, x86_64), true) JVM_EXCLUDE_PATTERNS += x86_32 endif -ifeq ($(call isTargetOs, windows), true) - ifeq ($(call isTargetCpuBits, 64), true) - RC_DESC := 64-Bit$(SPACE) - endif - JVM_RCFLAGS += -D"HS_FILEDESC=$(HOTSPOT_VM_DISTRO) $(RC_DESC)$(JVM_VARIANT) VM" -endif - JVM_OPTIMIZATION ?= HIGHEST_JVM # Need to set JVM_STRIPFLAGS to the default value from SPEC since the STRIPFLAGS @@ -168,8 +161,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJVM, \ USE_MAPFILE_FOR_SYMBOLS := true, \ STRIPFLAGS := $(JVM_STRIPFLAGS), \ EMBED_MANIFEST := true, \ - RC_FLAGS := $(JVM_RCFLAGS), \ - VERSIONINFO_RESOURCE := $(TOPDIR)/src/hotspot/os/windows/version.rc, \ + RC_FILEDESC := $(HOTSPOT_VM_DISTRO) $(OPENJDK_TARGET_CPU_BITS)-Bit $(JVM_VARIANT) VM, \ PRECOMPILED_HEADER := $(JVM_PRECOMPILED_HEADER), \ PRECOMPILED_HEADER_EXCLUDE := $(JVM_PRECOMPILED_HEADER_EXCLUDE), \ )) diff --git a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java index b385f8d7924..2ac123d87c8 100644 --- a/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java +++ b/make/langtools/src/classes/build/tools/symbolgenerator/CreateSymbols.java @@ -31,6 +31,7 @@ import build.tools.symbolgenerator.CreateSymbols .ModuleHeaderDescription .RequiresDescription; + import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.BufferedOutputStream; @@ -43,6 +44,7 @@ import java.io.OutputStream; import java.io.StringWriter; import java.io.Writer; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; @@ -220,7 +222,7 @@ public void createSymbols(String ctDescriptionFileExtra, String ctDescriptionFil long timestamp, String currentVersion, String systemModules) throws IOException { LoadDescriptions data = load(ctDescriptionFileExtra != null ? Paths.get(ctDescriptionFileExtra) : null, - Paths.get(ctDescriptionFile), null); + Paths.get(ctDescriptionFile)); splitHeaders(data.classes); @@ -303,7 +305,7 @@ private ZipEntry createZipEntry(String name, long timestamp) { public static String EXTENSION = ".sig"; - LoadDescriptions load(Path ctDescriptionWithExtraContent, Path ctDescriptionOpen, String deletePlatform) throws IOException { + LoadDescriptions load(Path ctDescriptionWithExtraContent, Path ctDescriptionOpen) throws IOException { Map platforms = new LinkedHashMap<>(); if (ctDescriptionWithExtraContent != null && Files.isRegularFile(ctDescriptionWithExtraContent)) { @@ -317,8 +319,7 @@ LoadDescriptions load(Path ctDescriptionWithExtraContent, Path ctDescriptionOpen case "platform": PlatformInput platform = PlatformInput.load(ctDescriptionWithExtraContent, reader); - if (!platform.version.equals(deletePlatform)) - platforms.put(platform.version, platform); + platforms.put(platform.version, platform); reader.moveNext(); break; default: @@ -336,13 +337,11 @@ LoadDescriptions load(Path ctDescriptionWithExtraContent, Path ctDescriptionOpen case "generate": String[] platformsAttr = reader.attributes.get("platforms").split(":"); generatePlatforms = new HashSet<>(List.of(platformsAttr)); - generatePlatforms.remove(deletePlatform); reader.moveNext(); break; case "platform": PlatformInput platform = PlatformInput.load(ctDescriptionOpen, reader); - if (!platform.version.equals(deletePlatform) && - !platforms.containsKey(platform.version)) + if (!platforms.containsKey(platform.version)) platforms.put(platform.version, platform); reader.moveNext(); break; @@ -408,18 +407,28 @@ LoadDescriptions load(Path ctDescriptionWithExtraContent, Path ctDescriptionOpen ClassList result = new ClassList(); - for (ClassDescription desc : classes.values()) { + classes.values().forEach(result::add); + return new LoadDescriptions(result, + modules, + new ArrayList<>(platforms.values())); + } + + private static void removeVersion(LoadDescriptions load, String deletePlatform) { + for (Iterator it = load.classes.iterator(); it.hasNext();) { + ClassDescription desc = it.next(); Iterator chdIt = desc.header.iterator(); while (chdIt.hasNext()) { ClassHeaderDescription chd = chdIt.next(); - chd.versions = reduce(chd.versions, generatePlatforms); - if (chd.versions.isEmpty()) + chd.versions = removeVersion(chd.versions, deletePlatform); + if (chd.versions.isEmpty()) { chdIt.remove(); + } } if (desc.header.isEmpty()) { + it.remove(); continue; } @@ -428,7 +437,7 @@ LoadDescriptions load(Path ctDescriptionWithExtraContent, Path ctDescriptionOpen while (methodIt.hasNext()) { MethodDescription method = methodIt.next(); - method.versions = reduce(method.versions, generatePlatforms); + method.versions = removeVersion(method.versions, deletePlatform); if (method.versions.isEmpty()) methodIt.remove(); } @@ -438,37 +447,29 @@ LoadDescriptions load(Path ctDescriptionWithExtraContent, Path ctDescriptionOpen while (fieldIt.hasNext()) { FieldDescription field = fieldIt.next(); - field.versions = reduce(field.versions, generatePlatforms); + field.versions = removeVersion(field.versions, deletePlatform); if (field.versions.isEmpty()) fieldIt.remove(); } - - result.add(desc); } - Map moduleList = new HashMap<>(); - - for (ModuleDescription desc : modules.values()) { + for (Iterator it = load.modules.values().iterator(); it.hasNext();) { + ModuleDescription desc = it.next(); Iterator mhdIt = desc.header.iterator(); while (mhdIt.hasNext()) { ModuleHeaderDescription mhd = mhdIt.next(); - mhd.versions = reduce(mhd.versions, generatePlatforms); + mhd.versions = removeVersion(mhd.versions, deletePlatform); if (mhd.versions.isEmpty()) mhdIt.remove(); } if (desc.header.isEmpty()) { + it.remove(); continue; } - - moduleList.put(desc.name, desc); } - - return new LoadDescriptions(result, - moduleList, - new ArrayList<>(platforms.values())); } static final class LoadDescriptions { @@ -550,6 +551,17 @@ private static String reduce(String original, Set generate) { return sb.toString(); } + private static String removeVersion(String original, String remove) { + StringBuilder sb = new StringBuilder(); + + for (char v : original.toCharArray()) { + if (v != remove.charAt(0)) { + sb.append(v); + } + } + return sb.toString(); + } + private static class PlatformInput { public final String version; public final String basePlatform; @@ -1271,24 +1283,9 @@ public void createBaseLine(List versions, Map modules = new HashMap<>(); for (VersionDescription desc : versions) { - List classFileData = new ArrayList<>(); - - try (BufferedReader descIn = - Files.newBufferedReader(Paths.get(desc.classes))) { - String line; - while ((line = descIn.readLine()) != null) { - ByteArrayOutputStream data = new ByteArrayOutputStream(); - for (int i = 0; i < line.length(); i += 2) { - String hex = line.substring(i, i + 2); - data.write(Integer.parseInt(hex, 16)); - } - classFileData.add(data.toByteArray()); - } - } catch (IOException ex) { - throw new IllegalStateException(ex); - } + Iterable classFileData = loadClassData(desc.classes); - loadVersionClasses(classes, modules, classFileData, excludesIncludes, desc.version); + loadVersionClasses(classes, modules, classFileData, excludesIncludes, desc.version, null); } List platforms = @@ -1299,7 +1296,7 @@ public void createBaseLine(List versions, null)) .collect(Collectors.toList()); - dumpDescriptions(classes, modules, platforms, descDest.resolve("symbols"), args); + dumpDescriptions(classes, modules, platforms, Set.of(), descDest.resolve("symbols"), args); } //where: private static final String DO_NO_MODIFY = @@ -1332,11 +1329,33 @@ public void createBaseLine(List versions, "# ##########################################################\n" + "#\n"; + private Iterable loadClassData(String path) { + List classFileData = new ArrayList<>(); + + try (BufferedReader descIn = + Files.newBufferedReader(Paths.get(path))) { + String line; + while ((line = descIn.readLine()) != null) { + ByteArrayOutputStream data = new ByteArrayOutputStream(); + for (int i = 0; i < line.length(); i += 2) { + String hex = line.substring(i, i + 2); + data.write(Integer.parseInt(hex, 16)); + } + classFileData.add(data.toByteArray()); + } + } catch (IOException ex) { + throw new IllegalStateException(ex); + } + + return classFileData; + } + private void loadVersionClasses(ClassList classes, Map modules, Iterable classData, ExcludeIncludeList excludesIncludes, - String version) { + String version, + String baseline) { Map currentVersionModules = new HashMap<>(); @@ -1460,12 +1479,12 @@ private void loadVersionClasses(ClassList classes, ClassDescription existing = classes.find(clazz.name, true); if (existing != null) { - addClassHeader(existing, header, version); + addClassHeader(existing, header, version, baseline); for (MethodDescription currentMethod : clazz.methods) { - addMethod(existing, currentMethod, version); + addMethod(existing, currentMethod, version, baseline); } for (FieldDescription currentField : clazz.fields) { - addField(existing, currentField, version); + addField(existing, currentField, version, baseline); } } else { classes.add(clazz); @@ -1502,6 +1521,7 @@ private void loadVersionClasses(ClassList classes, private void dumpDescriptions(ClassList classes, Map modules, List versions, + Set forceWriteVersions, Path ctDescriptionFile, String[] args) throws IOException { classes.sort(); @@ -1568,7 +1588,7 @@ private void dumpDescriptions(ClassList classes, for (PlatformInput desc : versions) { List files = desc.files; - if (files == null) { + if (files == null || forceWriteVersions.contains(desc.version)) { files = new ArrayList<>(); for (Entry> e : module2Classes.entrySet()) { StringWriter data = new StringWriter(); @@ -1586,9 +1606,34 @@ private void dumpDescriptions(ClassList classes, String dataString = data.toString(); if (!dataString.isEmpty()) { - try (Writer out = Files.newBufferedWriter(f)) { - out.append(DO_NO_MODIFY.replace("{YEAR}", String.valueOf(year))); - out.write(dataString); + String existingYear = null; + boolean hasChange = true; + if (Files.isReadable(f)) { + String oldContent = Files.readString(f, StandardCharsets.UTF_8); + int yearPos = DO_NO_MODIFY.indexOf("{YEAR}"); + String headerPattern = + Pattern.quote(DO_NO_MODIFY.substring(0, yearPos)) + + "([0-9]+)(, [0-9]+)?" + + Pattern.quote(DO_NO_MODIFY.substring(yearPos + "{YEAR}".length())); + String pattern = headerPattern + + Pattern.quote(dataString); + Matcher m = Pattern.compile(pattern, Pattern.MULTILINE).matcher(oldContent); + if (m.matches()) { + hasChange = false; + } else { + m = Pattern.compile(headerPattern).matcher(oldContent); + if (m.find()) { + existingYear = m.group(1); + } + } + } + if (hasChange) { + try (Writer out = Files.newBufferedWriter(f, StandardCharsets.UTF_8)) { + String currentYear = String.valueOf(year); + String yearSpec = (existingYear != null && !currentYear.equals(existingYear) ? existingYear + ", " : "") + currentYear; + out.append(DO_NO_MODIFY.replace("{YEAR}", yearSpec)); + out.write(dataString); + } } files.add(f.getFileName().toString()); } @@ -1630,15 +1675,17 @@ private void dumpDescriptions(ClassList classes, } } - public void createIncrementalBaseLine(String ctDescriptionFile, - String excludeFile, - String[] args) throws IOException { - String specVersion = System.getProperty("java.specification.version"); + private void incrementalUpdate(String ctDescriptionFile, + String excludeFile, + String platformVersion, + Iterable classBytes, + Function baseline, + String[] args) throws IOException { String currentVersion = - Integer.toString(Integer.parseInt(specVersion), Character.MAX_RADIX); - currentVersion = currentVersion.toUpperCase(Locale.ROOT); + Integer.toString(Integer.parseInt(platformVersion), Character.MAX_RADIX); + String version = currentVersion.toUpperCase(Locale.ROOT); Path ctDescriptionPath = Paths.get(ctDescriptionFile).toAbsolutePath(); - LoadDescriptions data = load(null, ctDescriptionPath, currentVersion); + LoadDescriptions data = load(null, ctDescriptionPath); ClassList classes = data.classes; Map modules = data.modules; @@ -1647,23 +1694,70 @@ public void createIncrementalBaseLine(String ctDescriptionFile, ExcludeIncludeList excludeList = ExcludeIncludeList.create(excludeFile); - Iterable classBytes = dumpCurrentClasses(); - loadVersionClasses(classes, modules, classBytes, excludeList, currentVersion); + loadVersionClasses(classes, modules, classBytes, excludeList, "$", version); + + removeVersion(data, version); - String baseline; + for (ModuleDescription md : data.modules.values()) { + for (ModuleHeaderDescription header : md.header) { + header.versions = header.versions.replace("$", version); + } + } - if (versions.isEmpty()) { - baseline = null; - } else { - baseline = versions.stream() - .sorted((v1, v2) -> v2.version.compareTo(v1.version)) - .findFirst() - .get() - .version; + for (ClassDescription clazzDesc : data.classes) { + for (ClassHeaderDescription header : clazzDesc.header) { + header.versions = header.versions.replace("$", version); + } + for (MethodDescription method : clazzDesc.methods) { + method.versions = method.versions.replace("$", version); + } + for (FieldDescription field : clazzDesc.fields) { + field.versions = field.versions.replace("$", version); + } } - versions.add(new PlatformInput(null, currentVersion, baseline, null)); - dumpDescriptions(classes, modules, versions, ctDescriptionPath, args); + if (versions.stream().noneMatch(inp -> version.equals(inp.version))) { + versions.add(new PlatformInput(null, version, baseline.apply(data), null)); + } + + Set writeVersions = new HashSet<>(); + + writeVersions.add(version); + + //re-write all platforms that have version as their basline: + versions.stream() + .filter(inp -> version.equals(inp.basePlatform)) + .map(inp -> inp.version) + .forEach(writeVersions::add); + dumpDescriptions(classes, modules, versions, writeVersions, ctDescriptionPath, args); + } + + public void createIncrementalBaseLineFromDataFile(String ctDescriptionFile, + String excludeFile, + String version, + String dataFile, + String baseline, + String[] args) throws IOException { + incrementalUpdate(ctDescriptionFile, excludeFile, version, loadClassData(dataFile), x -> baseline, args); + } + + public void createIncrementalBaseLine(String ctDescriptionFile, + String excludeFile, + String[] args) throws IOException { + String specVersion = System.getProperty("java.specification.version"); + Iterable classBytes = dumpCurrentClasses(); + Function baseline = data -> { + if (data.versions.isEmpty()) { + return null; + } else { + return data.versions.stream() + .sorted((v1, v2) -> v2.version.compareTo(v1.version)) + .findFirst() + .get() + .version; + } + }; + incrementalUpdate(ctDescriptionFile, excludeFile, specVersion, classBytes, baseline, args); } private List dumpCurrentClasses() throws IOException { @@ -1757,7 +1851,7 @@ private void inspectClassFile(InputStream in, ClassList classes, ExcludeIncludeL classes.add(clazzDesc); } - addClassHeader(clazzDesc, headerDesc, version); + addClassHeader(clazzDesc, headerDesc, version, null); for (Method m : cf.methods) { if (!include(m.access_flags.flags)) @@ -1769,7 +1863,7 @@ private void inspectClassFile(InputStream in, ClassList classes, ExcludeIncludeL for (Attribute attr : m.attributes) { readAttribute(cf, methDesc, attr); } - addMethod(clazzDesc, methDesc, version); + addMethod(clazzDesc, methDesc, version, null); } for (Field f : cf.fields) { if (!include(f.access_flags.flags)) @@ -1781,7 +1875,7 @@ private void inspectClassFile(InputStream in, ClassList classes, ExcludeIncludeL for (Attribute attr : f.attributes) { readAttribute(cf, fieldDesc, attr); } - addField(clazzDesc, fieldDesc, version); + addField(clazzDesc, fieldDesc, version, null); } } @@ -1840,11 +1934,11 @@ private boolean include(int accessFlags) { return (accessFlags & (AccessFlags.ACC_PUBLIC | AccessFlags.ACC_PROTECTED)) != 0; } - private void addClassHeader(ClassDescription clazzDesc, ClassHeaderDescription headerDesc, String version) { + private void addClassHeader(ClassDescription clazzDesc, ClassHeaderDescription headerDesc, String version, String baseline) { //normalize: boolean existed = false; for (ClassHeaderDescription existing : clazzDesc.header) { - if (existing.equals(headerDesc)) { + if (existing.equals(headerDesc) && (!existed || (baseline != null && existing.versions.contains(baseline)))) { headerDesc = existing; existed = true; } @@ -1880,14 +1974,13 @@ private void addClassHeader(ClassDescription clazzDesc, ClassHeaderDescription h } } - private void addMethod(ClassDescription clazzDesc, MethodDescription methDesc, String version) { + private void addMethod(ClassDescription clazzDesc, MethodDescription methDesc, String version, String baseline) { //normalize: boolean methodExisted = false; for (MethodDescription existing : clazzDesc.methods) { - if (existing.equals(methDesc)) { + if (existing.equals(methDesc) && (!methodExisted || (baseline != null && existing.versions.contains(baseline)))) { methodExisted = true; methDesc = existing; - break; } } methDesc.versions += version; @@ -1896,13 +1989,12 @@ private void addMethod(ClassDescription clazzDesc, MethodDescription methDesc, S } } - private void addField(ClassDescription clazzDesc, FieldDescription fieldDesc, String version) { + private void addField(ClassDescription clazzDesc, FieldDescription fieldDesc, String version, String baseline) { boolean fieldExisted = false; for (FieldDescription existing : clazzDesc.fields) { - if (existing.equals(fieldDesc)) { + if (existing.equals(fieldDesc) && (!fieldExisted || (baseline != null && existing.versions.contains(baseline)))) { fieldExisted = true; fieldDesc = existing; - break; } } fieldDesc.versions += version; @@ -2311,6 +2403,7 @@ static boolean checkChange(String versions, String version, } static abstract class FeatureDescription { + int flagsNormalization = ~0; int flags; boolean deprecated; String signature; @@ -2375,7 +2468,7 @@ protected void readAttributes(LineBasedReader reader) { @Override public int hashCode() { int hash = 3; - hash = 89 * hash + this.flags; + hash = 89 * hash + (this.flags & flagsNormalization); hash = 89 * hash + (this.deprecated ? 1 : 0); hash = 89 * hash + Objects.hashCode(this.signature); hash = 89 * hash + listHashCode(this.classAnnotations); @@ -2392,7 +2485,7 @@ public boolean equals(Object obj) { return false; } final FeatureDescription other = (FeatureDescription) obj; - if (this.flags != other.flags) { + if ((this.flags & flagsNormalization) != (other.flags & flagsNormalization)) { return false; } if (this.deprecated != other.deprecated) { @@ -3044,6 +3137,7 @@ protected void readInnerClasses(LineBasedReader reader) throws IOException { } static class MethodDescription extends FeatureDescription { + static int METHODS_FLAGS_NORMALIZATION = ~0; String name; String descriptor; List thrownTypes; @@ -3051,6 +3145,10 @@ static class MethodDescription extends FeatureDescription { List> classParameterAnnotations; List> runtimeParameterAnnotations; + public MethodDescription() { + flagsNormalization = METHODS_FLAGS_NORMALIZATION; + } + @Override public int hashCode() { int hash = super.hashCode(); @@ -3775,6 +3873,24 @@ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOExce args); break; } + case "build-description-incremental-file": { + if (args.length != 6 && args.length != 7) { + help(); + return ; + } + + if (args.length == 7) { + if ("--normalize-method-flags".equals(args[6])) { + MethodDescription.METHODS_FLAGS_NORMALIZATION = ~(0x100 | 0x20); + } else { + help(); + return ; + } + } + + new CreateSymbols().createIncrementalBaseLineFromDataFile(args[1], args[2], args[3], args[4], "".equals(args[5]) ? null : args[5], args); + break; + } case "build-description-incremental": { if (args.length != 3) { help(); diff --git a/make/modules/java.base/Launcher.gmk b/make/modules/java.base/Launcher.gmk index 3a04ee387ea..700ddefda49 100644 --- a/make/modules/java.base/Launcher.gmk +++ b/make/modules/java.base/Launcher.gmk @@ -30,14 +30,13 @@ $(eval $(call IncludeCustomExtension, modules/java.base/Launcher.gmk)) JAVA_VERSION_INFO_RESOURCE := $(TOPDIR)/src/java.base/windows/native/launcher/java.rc -JAVA_RC_FLAGS += -I$(TOPDIR)/src/java.base/windows/native/common -JAVA_RC_FLAGS += -I$(TOPDIR)/src/java.base/windows/native/launcher/icons +JAVA_RCFLAGS ?= -I$(TOPDIR)/src/java.base/windows/native/launcher/icons ################################################################################ $(eval $(call SetupBuildLauncher, java, \ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \ - EXTRA_RC_FLAGS := $(JAVA_RC_FLAGS), \ + EXTRA_RCFLAGS := $(JAVA_RCFLAGS), \ VERSION_INFO_RESOURCE := $(JAVA_VERSION_INFO_RESOURCE), \ OPTIMIZATION := HIGH, \ )) @@ -45,7 +44,7 @@ $(eval $(call SetupBuildLauncher, java, \ ifeq ($(call isTargetOs, windows), true) $(eval $(call SetupBuildLauncher, javaw, \ CFLAGS := -DJAVAW -DEXPAND_CLASSPATH_WILDCARDS -DENABLE_ARG_FILES, \ - EXTRA_RC_FLAGS := $(JAVA_RC_FLAGS), \ + EXTRA_RCFLAGS := $(JAVA_RCFLAGS), \ VERSION_INFO_RESOURCE := $(JAVA_VERSION_INFO_RESOURCE), \ )) endif diff --git a/make/modules/java.desktop/lib/Awt2dLibraries.gmk b/make/modules/java.desktop/lib/Awt2dLibraries.gmk index 4d7cddc49f8..f2ad3f55d84 100644 --- a/make/modules/java.desktop/lib/Awt2dLibraries.gmk +++ b/make/modules/java.desktop/lib/Awt2dLibraries.gmk @@ -116,7 +116,7 @@ ifeq ($(call isTargetOs, windows), true) LIBAWT_CFLAGS += -DMLIB_OS64BIT endif - LIBAWT_RC_FLAGS ?= -I $(TOPDIR)/src/java.base/windows/native/launcher/icons + LIBAWT_RCFLAGS ?= -I$(TOPDIR)/src/java.base/windows/native/launcher/icons LIBAWT_VERSIONINFO_RESOURCE := $(TOPDIR)/src/$(MODULE)/windows/native/libawt/windows/awt.rc endif @@ -169,10 +169,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \ comdlg32.lib winmm.lib comctl32.lib shlwapi.lib \ delayimp.lib jvm.lib $(WIN_JAVA_LIB) advapi32.lib, \ VERSIONINFO_RESOURCE := $(LIBAWT_VERSIONINFO_RESOURCE), \ - RC_FLAGS := $(RC_FLAGS) $(LIBAWT_RC_FLAGS) \ - -D "JDK_FNAME=awt.dll" \ - -D "JDK_INTERNAL_NAME=awt" \ - -D "JDK_FTYPE=0x2L", \ + EXTRA_RCFLAGS := $(LIBAWT_RCFLAGS), \ )) $(BUILD_LIBAWT): $(call FindLib, java.base, java) diff --git a/make/modules/jdk.accessibility/Launcher.gmk b/make/modules/jdk.accessibility/Launcher.gmk index 6364a7d3d8d..cf60d951a45 100644 --- a/make/modules/jdk.accessibility/Launcher.gmk +++ b/make/modules/jdk.accessibility/Launcher.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,17 +25,20 @@ include LauncherCommon.gmk -################################################################################ -# jabswitch - ifeq ($(call isTargetOs, windows), true) - JABSWITCH_SRC := $(TOPDIR)/src/jdk.accessibility/windows/native/jabswitch - ACCESSBRIDGE_SRC := $(TOPDIR)/src/jdk.accessibility/windows/native/common + ACCESSIBILITY_SRCDIR := $(TOPDIR)/src/jdk.accessibility/windows/native + TOOLS_CFLAGS := $(addprefix -I, \ + $(ACCESSIBILITY_SRCDIR)/include/bridge \ + $(ACCESSIBILITY_SRCDIR)/common \ + $(ACCESSIBILITY_SRCDIR)/toolscommon) + + ############################################################################## + # jabswitch $(eval $(call SetupJdkExecutable, BUILD_JABSWITCH, \ NAME := jabswitch, \ - SRC := $(JABSWITCH_SRC), \ + SRC := $(ACCESSIBILITY_SRCDIR)/jabswitch, \ INCLUDE_FILES := jabswitch.cpp, \ CFLAGS := $(filter-out -Zc:wchar_t-, $(CFLAGS_JDKEXE)) -Zc:wchar_t \ -analyze- -Od -Gd -D_WINDOWS \ @@ -43,21 +46,15 @@ ifeq ($(call isTargetOs, windows), true) DISABLED_WARNINGS_microsoft := 4267 4996, \ LDFLAGS := $(LDFLAGS_JDKEXE), \ LIBS := advapi32.lib version.lib user32.lib, \ - VERSIONINFO_RESOURCE := $(ACCESSBRIDGE_SRC)/AccessBridgeStatusWindow.rc, \ - MANIFEST := $(JABSWITCH_SRC)/jabswitch.manifest, \ + VERSIONINFO_RESOURCE := $(ACCESSIBILITY_SRCDIR)/common/AccessBridgeStatusWindow.rc, \ + MANIFEST := $(ACCESSIBILITY_SRCDIR)/jabswitch/jabswitch.manifest, \ MANIFEST_VERSION := $(VERSION_NUMBER_FOUR_POSITIONS), \ )) TARGETS += $(BUILD_JABSWITCH) -################################################################################ -# jaccessinspector - - TOPDIR := $(TOPDIR)/src/jdk.accessibility/windows/native - TOOLS_CFLAGS := $(addprefix -I, \ - $(TOPDIR)/include/bridge \ - $(TOPDIR)/common \ - $(TOPDIR)/toolscommon) + ############################################################################## + # jaccessinspector define SetupInspector # Parameter 1 File name suffix @@ -65,20 +62,20 @@ ifeq ($(call isTargetOs, windows), true) $$(eval $$(call SetupJdkExecutable, BUILD_JACCESSINSPECTOR$1, \ NAME := jaccessinspector$1, \ - SRC := $(TOPDIR)/jaccessinspector $(TOPDIR)/common \ - $(TOPDIR)/toolscommon $(TOPDIR)/bridge, \ + SRC := $(ACCESSIBILITY_SRCDIR)/jaccessinspector $(ACCESSIBILITY_SRCDIR)/common \ + $(ACCESSIBILITY_SRCDIR)/toolscommon $(ACCESSIBILITY_SRCDIR)/bridge, \ CFLAGS := $$(CFLAGS_JDKEXE) $(TOOLS_CFLAGS) -DACCESSBRIDGE_ARCH_$2 -EHsc, \ LDFLAGS := $$(LDFLAGS_JDKEXE) -stack:655360, \ LIBS := advapi32.lib user32.lib, \ - VERSIONINFO_RESOURCE := $(TOPDIR)/jaccessinspector/jaccessinspectorWindow.rc, \ + VERSIONINFO_RESOURCE := $(ACCESSIBILITY_SRCDIR)/jaccessinspector/jaccessinspectorWindow.rc, \ )) TARGETS += $$(BUILD_JACCESSINSPECTOR$1) endef -################################################################################ -# jaccesswalker + ############################################################################## + # jaccesswalker define SetupWalker # Parameter 1 File name suffix @@ -86,12 +83,12 @@ ifeq ($(call isTargetOs, windows), true) $$(eval $$(call SetupJdkExecutable, BUILD_JACCESSWALKER$1, \ NAME := jaccesswalker$1, \ - SRC := $(TOPDIR)/jaccesswalker $(TOPDIR)/common \ - $(TOPDIR)/toolscommon $(TOPDIR)/bridge, \ + SRC := $(ACCESSIBILITY_SRCDIR)/jaccesswalker $(ACCESSIBILITY_SRCDIR)/common \ + $(ACCESSIBILITY_SRCDIR)/toolscommon $(ACCESSIBILITY_SRCDIR)/bridge, \ CFLAGS := $$(CFLAGS_JDKEXE) $(TOOLS_CFLAGS) -DACCESSBRIDGE_ARCH_$2 -EHsc, \ LDFLAGS := $$(LDFLAGS_JDKEXE) -stack:655360, \ LIBS := advapi32.lib comctl32.lib gdi32.lib user32.lib, \ - VERSIONINFO_RESOURCE := $(TOPDIR)/jaccesswalker/jaccesswalkerWindow.rc, \ + VERSIONINFO_RESOURCE := $(ACCESSIBILITY_SRCDIR)/jaccesswalker/jaccesswalkerWindow.rc, \ )) TARGETS += $$(BUILD_JACCESSWALKER$1) diff --git a/make/modules/jdk.accessibility/Lib.gmk b/make/modules/jdk.accessibility/Lib.gmk index 1fa5d9fb24c..4954b2ca12e 100644 --- a/make/modules/jdk.accessibility/Lib.gmk +++ b/make/modules/jdk.accessibility/Lib.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ include LibCommon.gmk ifeq ($(call isTargetOs, windows), true) - ROOT_SRCDIR := $(TOPDIR)/src/jdk.accessibility/windows/native + ACCESSIBILITY_SRCDIR := $(TOPDIR)/src/jdk.accessibility/windows/native define SetupJavaDLL # Parameter 1 Suffix @@ -52,7 +52,7 @@ ifeq ($(call isTargetOs, windows), true) winspool.lib comdlg32.lib advapi32.lib shell32.lib \ $(SUPPORT_OUTPUTDIR)/native/java.desktop/libjawt/jawt.lib \ ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib, \ - VERSIONINFO_RESOURCE := $(ROOT_SRCDIR)/common/AccessBridgeStatusWindow.rc, \ + VERSIONINFO_RESOURCE := $(ACCESSIBILITY_SRCDIR)/common/AccessBridgeStatusWindow.rc, \ ) $$(BUILD_JAVAACCESSBRIDGE$1): $(call FindStaticLib, java.desktop, jawt, /libjawt) @@ -75,11 +75,11 @@ ifeq ($(call isTargetOs, windows), true) include/bridge \ java.base:include, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ - -def:$(ROOT_SRCDIR)/libwindowsaccessbridge/WinAccessBridge.DEF, \ + -def:$(ACCESSIBILITY_SRCDIR)/libwindowsaccessbridge/WinAccessBridge.DEF, \ LIBS := kernel32.lib user32.lib gdi32.lib \ winspool.lib comdlg32.lib advapi32.lib shell32.lib \ ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib, \ - VERSIONINFO_RESOURCE := $(ROOT_SRCDIR)/common/AccessBridgeStatusWindow.rc, \ + VERSIONINFO_RESOURCE := $(ACCESSIBILITY_SRCDIR)/common/AccessBridgeStatusWindow.rc, \ ) TARGETS += $$(BUILD_WINDOWSACCESSBRIDGE$1) @@ -93,7 +93,7 @@ ifeq ($(call isTargetOs, windows), true) OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB), \ LDFLAGS := $(LDFLAGS_JDKLIB), \ - VERSIONINFO_RESOURCE := $(ROOT_SRCDIR)/common/AccessBridgeStatusWindow.rc, \ + VERSIONINFO_RESOURCE := $(ACCESSIBILITY_SRCDIR)/common/AccessBridgeStatusWindow.rc, \ ) TARGETS += $$(BUILD_ACCESSBRIDGESYSINFO) diff --git a/make/test/BuildTestLib.gmk b/make/test/BuildTestLib.gmk index 833919a94fe..dff446eed3b 100644 --- a/make/test/BuildTestLib.gmk +++ b/make/test/BuildTestLib.gmk @@ -43,12 +43,14 @@ $(eval $(call SetupJavaCompilation, BUILD_WB_JAR, \ TARGETS += $(BUILD_WB_JAR) -# test-lib.jar will contain only hprof classes until JDK-8081381 is resolved $(eval $(call SetupJavaCompilation, BUILD_TEST_LIB_JAR, \ TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK_UPGRADED), \ - SRC := $(TEST_LIB_SOURCE_DIR)/jdk/test/lib/hprof, \ + SRC := $(TEST_LIB_SOURCE_DIR), \ + EXCLUDES := jdk/test/lib/containers jdk/test/lib/security, \ BIN := $(TEST_LIB_SUPPORT)/test-lib_classes, \ + HEADERS := $(TEST_LIB_SUPPORT)/test-lib_headers, \ JAR := $(TEST_LIB_SUPPORT)/test-lib.jar, \ + DISABLED_WARNINGS := try deprecation rawtypes unchecked serial cast, \ )) TARGETS += $(BUILD_TEST_LIB_JAR) diff --git a/make/test/BuildTestLibNative.gmk b/make/test/BuildTestLibNative.gmk new file mode 100644 index 00000000000..00c7607913b --- /dev/null +++ b/make/test/BuildTestLibNative.gmk @@ -0,0 +1,83 @@ +# +# 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. +# + +################################################################################ +# This file builds the native component of testlib. +# It also covers the test-image part, where the built files are copied to the +# test image. +################################################################################ + +default: all + +include $(SPEC) +include MakeBase.gmk +include TestFilesCompilation.gmk + +################################################################################ +# Targets for building the native tests themselves. +################################################################################ + +BUILD_LIBTEST_NATIVE_SRC := $(TOPDIR)/test/lib + +BUILD_LIBTEST_OUTPUT_DIR := $(OUTPUTDIR)/support/test/lib/native + +BUILD_LIBTEST_IMAGE_DIR := $(TEST_IMAGE_DIR)/lib + +# This evaluation is expensive and should only be done if this target was +# explicitly called. +ifneq ($(filter build-test-lib-native, $(MAKECMDGOALS)), ) + $(eval $(call SetupTestFilesCompilation, BUILD_LIBTEST_LIBRARIES, \ + TYPE := LIBRARY, \ + SOURCE_DIRS := $(BUILD_LIBTEST_NATIVE_SRC), \ + OUTPUT_DIR := $(BUILD_LIBTEST_OUTPUT_DIR), \ + )) +endif + +build-test-lib-native: $(BUILD_LIBTEST_LIBRARIES) + +################################################################################ +# Targets for building test-image. +################################################################################ + +# Copy to testlib test image. We need it in both hotspot and jdk. +$(eval $(call SetupCopyFiles, COPY_LIBTEST_NATIVE_TO_HOTSPOT, \ + SRC := $(BUILD_LIBTEST_OUTPUT_DIR), \ + DEST := $(TEST_IMAGE_DIR)/hotspot/jtreg/native, \ + FILES := $(wildcard $(addprefix $(BUILD_LIBTEST_OUTPUT_DIR), /lib/*)), \ + FLATTEN := true, \ +)) + +$(eval $(call SetupCopyFiles, COPY_LIBTEST_NATIVE_TO_JDK, \ + SRC := $(BUILD_LIBTEST_OUTPUT_DIR), \ + DEST := $(TEST_IMAGE_DIR)/jdk/jtreg/native, \ + FILES := $(wildcard $(addprefix $(BUILD_LIBTEST_OUTPUT_DIR), /lib/*)), \ + FLATTEN := true, \ +)) + +test-image-lib-native: $(COPY_LIBTEST_NATIVE_TO_HOTSPOT) $(COPY_LIBTEST_NATIVE_TO_JDK) + +all: build-test-lib-native + +.PHONY: default all build-test-lib-native test-image-lib-native diff --git a/make/test/JtregGraalUnit.gmk b/make/test/JtregGraalUnit.gmk index fcfbc3b864a..08426e69456 100644 --- a/make/test/JtregGraalUnit.gmk +++ b/make/test/JtregGraalUnit.gmk @@ -105,6 +105,7 @@ ifeq ($(INCLUDE_GRAAL), true) $(SRC_DIR)/org.graalvm.compiler.nodes.test/src \ $(SRC_DIR)/org.graalvm.compiler.options.test/src \ $(SRC_DIR)/org.graalvm.compiler.phases.common.test/src \ + $(SRC_DIR)/org.graalvm.compiler.replacements.jdk10.test/src \ $(SRC_DIR)/org.graalvm.compiler.replacements.jdk12.test/src \ $(SRC_DIR)/org.graalvm.compiler.replacements.jdk9.test/src \ $(SRC_DIR)/org.graalvm.compiler.replacements.test/src \ diff --git a/src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp index 363a8b095d3..18ed41c9bc7 100644 --- a/src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -30,6 +30,7 @@ #include "c1/c1_LIRAssembler.hpp" #include "c1/c1_MacroAssembler.hpp" #include "c1/c1_Runtime1.hpp" +#include "classfile/javaClasses.hpp" #include "nativeInst_aarch64.hpp" #include "runtime/sharedRuntime.hpp" #include "vmreg_aarch64.inline.hpp" @@ -136,7 +137,7 @@ void LoadFlattenedArrayStub::emit_code(LIR_Assembler* ce) { __ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::load_flattened_array_id))); ce->add_call_info_here(_info); ce->verify_oop_map(_info); - if (_result->as_register() != r0) { + if (_result->as_register() != r0) { __ mov(_result->as_register(), r0); } __ b(_continuation); @@ -288,7 +289,7 @@ void MonitorEnterStub::emit_code(LIR_Assembler* ce) { __ mov(rscratch2, markWord::always_locked_pattern); __ andr(rscratch1, rscratch1, rscratch2); - __ cmp(rscratch1, rscratch2); + __ cmp(rscratch1, rscratch2); __ br(Assembler::NE, *_throw_imse_stub->entry()); } diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp index e564f965ac4..44d73a46f43 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/c1/shenandoahBarrierSetC1_aarch64.cpp @@ -48,7 +48,7 @@ void LIR_OpShenandoahCompareAndSwap::emit_code(LIR_Assembler* masm) { newval = tmp2; } - ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm->masm(), addr, cmpval, newval, /*acquire*/ false, /*release*/ true, /*weak*/ false, /*is_cae*/ false, result); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm->masm(), addr, cmpval, newval, /*acquire*/ false, /*release*/ true, /*is_cae*/ false, result); } #undef __ diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp index 7a37c7caf10..9fa72a16f01 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp @@ -449,9 +449,64 @@ void ShenandoahBarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler __ bind(done); } - -void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler* masm, Register addr, Register expected, Register new_val, - bool acquire, bool release, bool weak, bool is_cae, +// Special Shenandoah CAS implementation that handles false negatives due +// to concurrent evacuation. The service is more complex than a +// traditional CAS operation because the CAS operation is intended to +// succeed if the reference at addr exactly matches expected or if the +// reference at addr holds a pointer to a from-space object that has +// been relocated to the location named by expected. There are two +// races that must be addressed: +// a) A parallel thread may mutate the contents of addr so that it points +// to a different object. In this case, the CAS operation should fail. +// b) A parallel thread may heal the contents of addr, replacing a +// from-space pointer held in addr with the to-space pointer +// representing the new location of the object. +// Upon entry to cmpxchg_oop, it is assured that new_val equals NULL +// or it refers to an object that is not being evacuated out of +// from-space, or it refers to the to-space version of an object that +// is being evacuated out of from-space. +// +// By default, this operation implements sequential consistency and the +// value held in the result register following execution of the +// generated code sequence is 0 to indicate failure of CAS, non-zero +// to indicate success. Arguments support variations on this theme: +// +// acquire: Allow relaxation of the memory ordering on CAS from +// sequential consistency. This can be useful when +// sequential consistency is not required, such as when +// another sequentially consistent operation is already +// present in the execution stream. If acquire, successful +// execution has the side effect of assuring that memory +// values updated by other threads and "released" will be +// visible to any read operations perfomed by this thread +// which follow this operation in program order. This is a +// special optimization that should not be enabled by default. +// release: Allow relaxation of the memory ordering on CAS from +// sequential consistency. This can be useful when +// sequential consistency is not required, such as when +// another sequentially consistent operation is already +// present in the execution stream. If release, successful +// completion of this operation has the side effect of +// assuring that all writes to memory performed by this +// thread that precede this operation in program order are +// visible to all other threads that subsequently "acquire" +// before reading the respective memory values. This is a +// special optimization that should not be enabled by default. +// is_cae: This turns CAS (compare and swap) into CAE (compare and +// exchange). This HotSpot convention is that CAE makes +// available to the caller the "failure witness", which is +// the value that was stored in memory which did not match +// the expected value. If is_cae, the result is the value +// most recently fetched from addr rather than a boolean +// success indicator. +// +// Clobbers rscratch1, rscratch2 +void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler* masm, + Register addr, + Register expected, + Register new_val, + bool acquire, bool release, + bool is_cae, Register result) { Register tmp1 = rscratch1; Register tmp2 = rscratch2; @@ -460,48 +515,124 @@ void ShenandoahBarrierSetAssembler::cmpxchg_oop(MacroAssembler* masm, Register a assert_different_registers(addr, expected, new_val, tmp1, tmp2); - Label retry, done, fail; + Label step4, done; - // CAS, using LL/SC pair. - __ bind(retry); - __ load_exclusive(tmp1, addr, size, acquire); - if (is_narrow) { - __ cmpw(tmp1, expected); - } else { - __ cmp(tmp1, expected); - } - __ br(Assembler::NE, fail); - __ store_exclusive(tmp2, new_val, addr, size, release); - if (weak) { - __ cmpw(tmp2, 0u); // If the store fails, return NE to our caller - } else { - __ cbnzw(tmp2, retry); - } - __ b(done); + // There are two ways to reach this label. Initial entry into the + // cmpxchg_oop code expansion starts at step1 (which is equivalent + // to label step4). Additionally, in the rare case that four steps + // are required to perform the requested operation, the fourth step + // is the same as the first. On a second pass through step 1, + // control may flow through step 2 on its way to failure. It will + // not flow from step 2 to step 3 since we are assured that the + // memory at addr no longer holds a from-space pointer. + // + // The comments that immediately follow the step4 label apply only + // to the case in which control reaches this label by branch from + // step 3. + + __ bind (step4); + + // Step 4. CAS has failed because the value most recently fetched + // from addr (which is now held in tmp1) is no longer the from-space + // pointer held in tmp2. If a different thread replaced the + // in-memory value with its equivalent to-space pointer, then CAS + // may still be able to succeed. The value held in the expected + // register has not changed. + // + // It is extremely rare we reach this point. For this reason, the + // implementation opts for smaller rather than potentially faster + // code. Ultimately, smaller code for this rare case most likely + // delivers higher overall throughput by enabling improved icache + // performance. + + // Step 1. Fast-path. + // + // Try to CAS with given arguments. If successful, then we are done. + // + // No label required for step 1. + + __ cmpxchg(addr, expected, new_val, size, acquire, release, false, tmp2); + // EQ flag set iff success. tmp2 holds value fetched. + + // If expected equals null but tmp2 does not equal null, the + // following branches to done to report failure of CAS. If both + // expected and tmp2 equal null, the following branches to done to + // report success of CAS. There's no need for a special test of + // expected equal to null. + + __ br(Assembler::EQ, done); + // if CAS failed, fall through to step 2 + + // Step 2. CAS has failed because the value held at addr does not + // match expected. This may be a false negative because the value fetched + // from addr (now held in tmp2) may be a from-space pointer to the + // original copy of same object referenced by to-space pointer expected. + // + // To resolve this, it suffices to find the forward pointer associated + // with fetched value. If this matches expected, retry CAS with new + // parameters. If this mismatches, then we have a legitimate + // failure, and we're done. + // + // No need for step2 label. + + // overwrite tmp1 with from-space pointer fetched from memory + __ mov(tmp1, tmp2); - __ bind(fail); - // Check if rb(expected)==rb(tmp1) - // Shuffle registers so that we have memory value ready for next expected. - __ mov(tmp2, expected); - __ mov(expected, tmp1); if (is_narrow) { + // Decode tmp1 in order to resolve its forward pointer __ decode_heap_oop(tmp1, tmp1); - __ decode_heap_oop(tmp2, tmp2); } resolve_forward_pointer(masm, tmp1); - resolve_forward_pointer(masm, tmp2); - __ cmp(tmp1, tmp2); - // Retry with expected now being the value we just loaded from addr. - __ br(Assembler::EQ, retry); - if (is_cae && is_narrow) { - // For cmp-and-exchange and narrow oops, we need to restore - // the compressed old-value. We moved it to 'expected' a few lines up. - __ mov(tmp1, expected); + // Encode tmp1 to compare against expected. + __ encode_heap_oop(tmp1, tmp1); + + // Does forwarded value of fetched from-space pointer match original + // value of expected? If tmp1 holds null, this comparison will fail + // because we know from step1 that expected is not null. There is + // no need for a separate test for tmp1 (the value originally held + // in memory) equal to null. + __ cmp(tmp1, expected); + + // If not, then the failure was legitimate and we're done. + // Branching to done with NE condition denotes failure. + __ br(Assembler::NE, done); + + // Fall through to step 3. No need for step3 label. + + // Step 3. We've confirmed that the value originally held in memory + // (now held in tmp2) pointed to from-space version of original + // expected value. Try the CAS again with the from-space expected + // value. If it now succeeds, we're good. + // + // Note: tmp2 holds encoded from-space pointer that matches to-space + // object residing at expected. tmp2 is the new "expected". + + // Note that macro implementation of __cmpxchg cannot use same register + // tmp2 for result and expected since it overwrites result before it + // compares result with expected. + __ cmpxchg(addr, tmp2, new_val, size, acquire, release, false, tmp1); + // EQ flag set iff success. tmp2 holds value fetched. + + // If fetched value did not equal the new expected, this could + // still be a false negative because some other thread may have + // newly overwritten the memory value with its to-space equivalent. + __ br(Assembler::NE, step4); + + if (is_cae) { + // We're falling through to done to indicate success. Success + // with is_cae is denoted by returning the value of expected as + // result. + __ mov(tmp2, expected); } + __ bind(done); + // At entry to done, the Z (EQ) flag is on iff if the CAS + // operation was successful. Additionally, if is_cae, tmp2 holds + // the value most recently fetched from addr. In this case, success + // is denoted by tmp2 matching expected. if (is_cae) { - __ mov(result, tmp1); + __ mov(result, tmp2); } else { __ cset(result, Assembler::EQ); } diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp index e2a45425235..88aa9a2b95f 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.hpp @@ -84,7 +84,7 @@ class ShenandoahBarrierSetAssembler: public BarrierSetAssembler { virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register jni_env, Register obj, Register tmp, Label& slowpath); void cmpxchg_oop(MacroAssembler* masm, Register addr, Register expected, Register new_val, - bool acquire, bool release, bool weak, bool is_cae, Register result); + bool acquire, bool release, bool is_cae, Register result); virtual void barrier_stubs_init(); }; diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoah_aarch64.ad b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoah_aarch64.ad index 143111289f2..091bf091d10 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoah_aarch64.ad +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoah_aarch64.ad @@ -33,7 +33,7 @@ encode %{ Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, - /*acquire*/ false, /*release*/ true, /*weak*/ false, /*is_cae*/ false, $res$$Register); + /*acquire*/ false, /*release*/ true, /*is_cae*/ false, $res$$Register); %} enc_class aarch64_enc_cmpxchg_acq_oop_shenandoah(memory mem, iRegP oldval, iRegP newval, iRegPNoSp tmp, iRegINoSp res) %{ @@ -42,7 +42,7 @@ encode %{ Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, - /*acquire*/ true, /*release*/ true, /*weak*/ false, /*is_cae*/ false, $res$$Register); + /*acquire*/ true, /*release*/ true, /*is_cae*/ false, $res$$Register); %} %} @@ -76,7 +76,7 @@ instruct compareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldval, i ins_encode %{ Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. - ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, /*acquire*/ false, /*release*/ true, /*weak*/ false, /*is_cae*/ false, $res$$Register); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, /*acquire*/ false, /*release*/ true, /*is_cae*/ false, $res$$Register); %} ins_pipe(pipe_slow); @@ -114,7 +114,7 @@ instruct compareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN oldval ins_encode %{ Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. - ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, /*acquire*/ true, /*release*/ true, /*weak*/ false, /*is_cae*/ false, $res$$Register); + ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, /*acquire*/ true, /*release*/ true, /*is_cae*/ false, $res$$Register); %} ins_pipe(pipe_slow); @@ -131,7 +131,7 @@ instruct compareAndExchangeN_shenandoah(iRegNNoSp res, indirect mem, iRegN oldva Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, - /*acquire*/ false, /*release*/ true, /*weak*/ false, /*is_cae*/ true, $res$$Register); + /*acquire*/ false, /*release*/ true, /*is_cae*/ true, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -147,7 +147,7 @@ instruct compareAndExchangeP_shenandoah(iRegPNoSp res, indirect mem, iRegP oldva Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, - /*acquire*/ false, /*release*/ true, /*weak*/ false, /*is_cae*/ true, $res$$Register); + /*acquire*/ false, /*release*/ true, /*is_cae*/ true, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -164,7 +164,7 @@ instruct compareAndExchangeNAcq_shenandoah(iRegNNoSp res, indirect mem, iRegN ol Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, - /*acquire*/ true, /*release*/ true, /*weak*/ false, /*is_cae*/ true, $res$$Register); + /*acquire*/ true, /*release*/ true, /*is_cae*/ true, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -181,7 +181,7 @@ instruct compareAndExchangePAcq_shenandoah(iRegPNoSp res, indirect mem, iRegP ol Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, - /*acquire*/ true, /*release*/ true, /*weak*/ false, /*is_cae*/ true, $res$$Register); + /*acquire*/ true, /*release*/ true, /*is_cae*/ true, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -197,8 +197,9 @@ instruct weakCompareAndSwapN_shenandoah(iRegINoSp res, indirect mem, iRegN oldva ins_encode %{ Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. + // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, - /*acquire*/ false, /*release*/ true, /*weak*/ true, /*is_cae*/ false, $res$$Register); + /*acquire*/ false, /*release*/ true, /*is_cae*/ false, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -213,8 +214,9 @@ instruct weakCompareAndSwapP_shenandoah(iRegINoSp res, indirect mem, iRegP oldva ins_encode %{ Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. + // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, - /*acquire*/ false, /*release*/ true, /*weak*/ true, /*is_cae*/ false, $res$$Register); + /*acquire*/ false, /*release*/ true, /*is_cae*/ false, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -231,8 +233,9 @@ instruct weakCompareAndSwapNAcq_shenandoah(iRegINoSp res, indirect mem, iRegN ol ins_encode %{ Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. + // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, - /*acquire*/ true, /*release*/ true, /*weak*/ true, /*is_cae*/ false, $res$$Register); + /*acquire*/ true, /*release*/ true, /*is_cae*/ false, $res$$Register); %} ins_pipe(pipe_slow); %} @@ -249,8 +252,9 @@ instruct weakCompareAndSwapPAcq_shenandoah(iRegINoSp res, indirect mem, iRegP ol ins_encode %{ Register tmp = $tmp$$Register; __ mov(tmp, $oldval$$Register); // Must not clobber oldval. + // Weak is not currently supported by ShenandoahBarrierSet::cmpxchg_oop ShenandoahBarrierSet::assembler()->cmpxchg_oop(&_masm, $mem$$Register, tmp, $newval$$Register, - /*acquire*/ true, /*release*/ true, /*weak*/ true, /*is_cae*/ false, $res$$Register); + /*acquire*/ true, /*release*/ true, /*is_cae*/ false, $res$$Register); %} ins_pipe(pipe_slow); %} diff --git a/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp b/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp index 12a9f6036ae..3156b4b8e83 100644 --- a/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp @@ -21,7 +21,8 @@ * questions. */ -#include "jvmci/jvmciCodeInstaller.hpp" + #include "jvmci/jvmci.hpp" + #include "jvmci/jvmciCodeInstaller.hpp" #include "jvmci/jvmciRuntime.hpp" #include "jvmci/jvmciCompilerToVM.hpp" #include "jvmci/jvmciJavaClasses.hpp" @@ -72,12 +73,12 @@ void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, JVMCIObject consta if (jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant)) { narrowKlass narrowOop = record_narrow_metadata_reference(_instructions, pc, constant, JVMCI_CHECK); MacroAssembler::patch_narrow_klass(pc, narrowOop); - TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/0x%x", p2i(pc), narrowOop); + JVMCI_event_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/0x%x", p2i(pc), narrowOop); } else { NativeMovConstReg* move = nativeMovConstReg_at(pc); void* reference = record_metadata_reference(_instructions, pc, constant, JVMCI_CHECK); move->set_data((intptr_t) reference); - TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(reference)); + JVMCI_event_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(reference)); } } @@ -88,7 +89,7 @@ void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset || (NativeInstruction::maybe_cpool_ref(pc))) { address dest = _constants->start() + data_offset; _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS)); - TRACE_jvmci_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset); + JVMCI_event_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset); } else { JVMCI_ERROR("unknown load or move instruction at " PTR_FORMAT, p2i(pc)); } @@ -115,7 +116,7 @@ void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong forei } else { JVMCI_ERROR("unknown call or jump instruction at " PTR_FORMAT, p2i(pc)); } - TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst)); + JVMCI_event_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst)); } void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &cbuf, JVMCIObject hotspot_method, jint pc_offset, JVMCI_TRAPS) { diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp index 1d4fa2fb246..abd24b79b67 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2018, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" +#include "code/codeCache.hpp" #include "code/compiledIC.hpp" #include "memory/resourceArea.hpp" #include "nativeInst_aarch64.hpp" diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp index c991ff57fb9..da8ae97887a 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2108, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -102,9 +102,6 @@ class NativeInstruction { public: - // unit test stuff - static void test() {} // override for testing - inline friend NativeInstruction* nativeInstruction_at(address address); static bool is_adrp_at(address instr); @@ -321,9 +318,6 @@ class NativeMovConstReg: public NativeInstruction { void verify(); void print(); - // unit test stuff - static void test() {} - // Creation inline friend NativeMovConstReg* nativeMovConstReg_at(address address); inline friend NativeMovConstReg* nativeMovConstReg_before(address address); @@ -397,9 +391,6 @@ class NativeMovRegMem: public NativeInstruction { void verify(); void print (); - // unit test stuff - static void test() {} - private: inline friend NativeMovRegMem* nativeMovRegMem_at (address address); }; @@ -432,8 +423,6 @@ class NativeLoadAddress: public NativeInstruction { void verify(); void print (); - // unit test stuff - static void test() {} }; // adrp x16, #page @@ -488,9 +477,6 @@ class NativeJump: public NativeInstruction { void verify(); - // Unit testing stuff - static void test() {} - // Insertion of native jump instruction static void insert(address code_pos, address entry); // MT-safe insertion of native jump at verified method entry diff --git a/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp b/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp index 9b80b0b48ec..49cc3207098 100644 --- a/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.hpp" +#include "code/compiledMethod.hpp" #include "code/relocInfo.hpp" #include "nativeInst_aarch64.hpp" #include "oops/oop.inline.hpp" diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index a3e99772431..3561b098d9f 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -27,6 +27,7 @@ #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" #include "classfile/symbolTable.hpp" +#include "code/codeCache.hpp" #include "code/debugInfoRec.hpp" #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp index e4b78a1beb0..66ba67645cc 100644 --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp @@ -3197,6 +3197,9 @@ void TemplateTable::fast_storefield(TosState state) // access constant pool cache __ get_cache_and_index_at_bcp(r2, r1, 1); + // Must prevent reordering of the following cp cache loads with bytecode load + __ membar(MacroAssembler::LoadLoad); + // test for volatile with r3 __ ldrw(r3, Address(r2, in_bytes(base + ConstantPoolCacheEntry::flags_offset()))); @@ -3302,6 +3305,10 @@ void TemplateTable::fast_accessfield(TosState state) // access constant pool cache __ get_cache_and_index_at_bcp(r2, r1, 1); + + // Must prevent reordering of the following cp cache loads with bytecode load + __ membar(MacroAssembler::LoadLoad); + __ ldr(r1, Address(r2, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset()))); __ ldrw(r3, Address(r2, in_bytes(ConstantPoolCache::base_offset() + diff --git a/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp b/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp index 392e29f504e..915eb73730c 100644 --- a/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp +++ b/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp @@ -29,6 +29,7 @@ #include "c1/c1_LIRAssembler.hpp" #include "c1/c1_MacroAssembler.hpp" #include "c1/c1_Runtime1.hpp" +#include "classfile/javaClasses.hpp" #include "memory/universe.hpp" #include "nativeInst_arm.hpp" #include "runtime/sharedRuntime.hpp" diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp index 64294d8e8ce..b20c279a624 100644 --- a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp +++ b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -145,9 +145,6 @@ class RawNativeInstruction { bool is_movt() const { return (encoding() & 0x0ff00000) == 0x03400000; } // c2 doesn't use fixed registers for safepoint poll address bool is_safepoint_poll() const { return (encoding() & 0xfff0ffff) == 0xe590c000; } - // For unit tests - static void test() {} - }; inline RawNativeInstruction* rawNativeInstruction_at(address address) { diff --git a/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp b/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp index 124bfe70429..b13e18efc12 100644 --- a/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp @@ -30,6 +30,7 @@ #include "c1/c1_LIRAssembler.hpp" #include "c1/c1_MacroAssembler.hpp" #include "c1/c1_Runtime1.hpp" +#include "classfile/javaClasses.hpp" #include "nativeInst_ppc.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/macros.hpp" diff --git a/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp b/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp index 67d7b9d1eee..367d2a43af5 100644 --- a/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp +++ b/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp @@ -30,6 +30,7 @@ #include "c1/c1_LIRAssembler.hpp" #include "c1/c1_MacroAssembler.hpp" #include "c1/c1_Runtime1.hpp" +#include "classfile/javaClasses.hpp" #include "nativeInst_s390.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/align.hpp" diff --git a/src/hotspot/cpu/s390/nativeInst_s390.hpp b/src/hotspot/cpu/s390/nativeInst_s390.hpp index 2ab17fedc12..09bb659a59d 100644 --- a/src/hotspot/cpu/s390/nativeInst_s390.hpp +++ b/src/hotspot/cpu/s390/nativeInst_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -137,9 +137,6 @@ class NativeInstruction { void verify(); - // unit test stuff - static void test() {} // Override for testing. - friend NativeInstruction* nativeInstruction_at(address address) { NativeInstruction* inst = (NativeInstruction*)address; #ifdef ASSERT @@ -274,9 +271,6 @@ class NativeCall: public NativeInstruction { void verify_alignment() {} // Yet another real do nothing guy :) void verify(); - // unit test stuff - static void test(); - // Creation. friend NativeCall* nativeCall_at(address instr) { NativeCall* call; @@ -443,9 +437,6 @@ class NativeFarCall: public NativeInstruction { void verify(); - // Unit tests - static void test(); - // Instantiates a NativeFarCall object starting at the given instruction // address and returns the NativeFarCall object. inline friend NativeFarCall* nativeFarCall_at(address instr) { @@ -500,9 +491,6 @@ class NativeMovConstReg: public NativeInstruction { void verify(); - // unit test stuff - static void test(); - // Creation. friend NativeMovConstReg* nativeMovConstReg_at(address address) { NativeMovConstReg* test = (NativeMovConstReg*)address; @@ -618,9 +606,6 @@ class NativeJump: public NativeInstruction { void verify(); - // Unit testing stuff - static void test(); - // Insertion of native jump instruction. static void insert(address code_pos, address entry); diff --git a/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp b/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp index 4d6e7823b84..6b3ee2bdd9b 100644 --- a/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp +++ b/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp @@ -28,6 +28,7 @@ #include "c1/c1_LIRAssembler.hpp" #include "c1/c1_MacroAssembler.hpp" #include "c1/c1_Runtime1.hpp" +#include "classfile/javaClasses.hpp" #include "nativeInst_x86.hpp" #include "oops/objArrayKlass.hpp" #include "runtime/sharedRuntime.hpp" diff --git a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp index d15ff335751..56c1bbdc34a 100644 --- a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp +++ b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp @@ -27,6 +27,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" #include "runtime/sharedRuntime.hpp" +#include "jvmci/jvmci.hpp" #include "jvmci/jvmciEnv.hpp" #include "jvmci/jvmciCodeInstaller.hpp" #include "jvmci/jvmciJavaClasses.hpp" @@ -74,7 +75,7 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, JVMCIObject constant, JV address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand); int oop_index = _oop_recorder->find_index(value); _instructions->relocate(pc, oop_Relocation::spec(oop_index), Assembler::narrow_oop_operand); - TRACE_jvmci_3("relocating (narrow oop constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand)); + JVMCI_event_3("relocating (narrow oop constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand)); #else JVMCI_ERROR("compressed oop on 32bit"); #endif @@ -82,7 +83,7 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, JVMCIObject constant, JV address operand = Assembler::locate_operand(pc, Assembler::imm_operand); *((jobject*) operand) = value; _instructions->relocate(pc, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); - TRACE_jvmci_3("relocating (oop constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand)); + JVMCI_event_3("relocating (oop constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand)); } } @@ -92,14 +93,14 @@ void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, JVMCIObject consta #ifdef _LP64 address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand); *((narrowKlass*) operand) = record_narrow_metadata_reference(_instructions, operand, constant, JVMCI_CHECK); - TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand)); + JVMCI_event_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand)); #else JVMCI_ERROR("compressed Klass* on 32bit"); #endif } else { address operand = Assembler::locate_operand(pc, Assembler::imm_operand); *((void**) operand) = record_metadata_reference(_instructions, operand, constant, JVMCI_CHECK); - TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand)); + JVMCI_event_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand)); } } @@ -115,7 +116,7 @@ void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset *((jint*) operand) = (jint) disp; _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS), Assembler::disp32_operand); - TRACE_jvmci_3("relocating at " PTR_FORMAT "/" PTR_FORMAT " with destination at " PTR_FORMAT " (%d)", p2i(pc), p2i(operand), p2i(dest), data_offset); + JVMCI_event_3("relocating at " PTR_FORMAT "/" PTR_FORMAT " with destination at " PTR_FORMAT " (%d)", p2i(pc), p2i(operand), p2i(dest), data_offset); } void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination, JVMCI_TRAPS) { @@ -143,7 +144,7 @@ void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong forei JVMCI_ERROR("unsupported relocation for foreign call"); } - TRACE_jvmci_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst)); + JVMCI_event_3("relocating (foreign call) at " PTR_FORMAT, p2i(inst)); } void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, JVMCIObject hotspot_method, jint pc_offset, JVMCI_TRAPS) { diff --git a/src/hotspot/cpu/x86/nativeInst_x86.hpp b/src/hotspot/cpu/x86/nativeInst_x86.hpp index 2db7fbe2c16..56296f86a56 100644 --- a/src/hotspot/cpu/x86/nativeInst_x86.hpp +++ b/src/hotspot/cpu/x86/nativeInst_x86.hpp @@ -94,9 +94,6 @@ class NativeInstruction { public: - // unit test stuff - static void test() {} // override for testing - inline friend NativeInstruction* nativeInstruction_at(address address); }; @@ -277,9 +274,6 @@ class NativeMovConstReg: public NativeInstruction { void verify(); void print(); - // unit test stuff - static void test() {} - // Creation inline friend NativeMovConstReg* nativeMovConstReg_at(address address); inline friend NativeMovConstReg* nativeMovConstReg_before(address address); @@ -393,9 +387,6 @@ class NativeMovRegMem: public NativeInstruction { void verify(); void print (); - // unit test stuff - static void test() {} - private: int patch_offset() const; inline friend NativeMovRegMem* nativeMovRegMem_at (address address); @@ -432,9 +423,6 @@ class NativeLoadAddress: public NativeMovRegMem { void verify(); void print (); - // unit test stuff - static void test() {} - private: friend NativeLoadAddress* nativeLoadAddress_at (address address) { NativeLoadAddress* test = (NativeLoadAddress*)(address - instruction_offset); @@ -536,9 +524,6 @@ class NativeJump: public NativeInstruction { void verify(); - // Unit testing stuff - static void test() {} - // Insertion of native jump instruction static void insert(address code_pos, address entry); // MT-safe insertion of native jump at verified method entry @@ -564,9 +549,6 @@ class NativeFarJump: public NativeInstruction { void verify(); - // Unit testing stuff - static void test() {} - }; inline NativeFarJump* nativeFarJump_at(address address) { diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 0522dc559d9..6bf23c81759 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -1637,10 +1637,7 @@ bool Matcher::const_oop_prefer_decode() { } bool Matcher::const_klass_prefer_decode() { - // TODO: Either support matching DecodeNKlass (heap-based) in operand - // or condisider the following: - // Prefer ConNKlass+DecodeNKlass over ConP in simple compressed klass mode. - //return CompressedKlassPointers::base() == NULL; + // Prefer ConP over ConNKlass+DecodeNKlass. return true; } diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 698407b7807..d4f42c8841a 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -30,6 +30,7 @@ #include "classfile/classLoader.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" +#include "code/codeCache.hpp" #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" #include "compiler/compileBroker.hpp" diff --git a/src/hotspot/os/windows/version.rc b/src/hotspot/os/windows/version.rc deleted file mode 100644 index b219d3c24f7..00000000000 --- a/src/hotspot/os/windows/version.rc +++ /dev/null @@ -1,72 +0,0 @@ -// -// Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. -// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -// -// This code is free software; you can redistribute it and/or modify it -// under the terms of the GNU General Public License version 2 only, as -// published by the Free Software Foundation. -// -// This code is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// version 2 for more details (a copy is included in the LICENSE file that -// accompanied this code). -// -// You should have received a copy of the GNU General Public License version -// 2 along with this work; if not, write to the Free Software Foundation, -// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -// -// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -// or visit www.oracle.com if you need additional information or have any -// questions. -// -// - -#include "winresrc.h" - -// Need 2 defines so macro argument to XSTR will get expanded before quoting. -#define XSTR(x) STR(x) -#define STR(x) #x - -LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION HS_FVER - PRODUCTVERSION HS_FVER - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - // FILEOS 0x4 is Win32, 0x40004 is Win32 NT only - FILEOS 0x4L - // FILETYPE should be 0x1 for .exe and 0x2 for .dll - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "CompanyName", XSTR(HS_COMPANY) "\0" - VALUE "FileDescription", XSTR(HS_FILEDESC) "\0" - VALUE "FileVersion", XSTR(HS_VER) "\0" - VALUE "Full Version", XSTR(HS_VERSION_STRING) "\0" - VALUE "InternalName", XSTR(HS_INTERNAL_NAME) "\0" - VALUE "LegalCopyright", XSTR(HS_COPYRIGHT) "\0" - VALUE "OriginalFilename", XSTR(HS_FNAME) "\0" - VALUE "ProductName", XSTR(HS_NAME) "\0" - VALUE "ProductVersion", XSTR(HS_VER) "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END diff --git a/src/hotspot/share/adlc/main.cpp b/src/hotspot/share/adlc/main.cpp index f23bd386f80..12ea916a425 100644 --- a/src/hotspot/share/adlc/main.cpp +++ b/src/hotspot/share/adlc/main.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -211,6 +211,7 @@ int main(int argc, char *argv[]) AD.addInclude(AD._CPP_file, "adfiles", get_basename(AD._VM_file._name)); AD.addInclude(AD._CPP_file, "adfiles", get_basename(AD._HPP_file._name)); AD.addInclude(AD._CPP_file, "memory/allocation.inline.hpp"); + AD.addInclude(AD._CPP_file, "code/codeCache.hpp"); AD.addInclude(AD._CPP_file, "code/compiledIC.hpp"); AD.addInclude(AD._CPP_file, "code/nativeInst.hpp"); AD.addInclude(AD._CPP_file, "code/vmreg.inline.hpp"); diff --git a/src/hotspot/share/c1/c1_Compilation.cpp b/src/hotspot/share/c1/c1_Compilation.cpp index 14cd2c58b19..836abd038f7 100644 --- a/src/hotspot/share/c1/c1_Compilation.cpp +++ b/src/hotspot/share/c1/c1_Compilation.cpp @@ -463,7 +463,7 @@ void Compilation::compile_method() { // Note: make sure we mark the method as not compilable! CHECK_BAILOUT(); - if (InstallMethods) { + if (should_install_code()) { // install code PhaseTraceTime timeit(_t_codeinstall); install_code(frame_size); @@ -539,7 +539,7 @@ void Compilation::generate_exception_handler_table() { } Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method, - int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive) + int osr_bci, BufferBlob* buffer_blob, bool install_code, DirectiveSet* directive) : _next_id(0) , _next_block_id(0) , _compiler(compiler) @@ -558,6 +558,7 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho , _would_profile(false) , _has_method_handle_invokes(false) , _has_reserved_stack_access(method->has_reserved_stack_access()) +, _install_code(install_code) , _bailout_msg(NULL) , _exception_info_list(NULL) , _allocator(NULL) diff --git a/src/hotspot/share/c1/c1_Compilation.hpp b/src/hotspot/share/c1/c1_Compilation.hpp index f2f687c696c..ad33ef27b58 100644 --- a/src/hotspot/share/c1/c1_Compilation.hpp +++ b/src/hotspot/share/c1/c1_Compilation.hpp @@ -82,6 +82,7 @@ class Compilation: public StackObj { bool _would_profile; bool _has_method_handle_invokes; // True if this method has MethodHandle invokes. bool _has_reserved_stack_access; + bool _install_code; const char* _bailout_msg; ExceptionInfoList* _exception_info_list; ExceptionHandlerTable _exception_handler_table; @@ -122,7 +123,7 @@ class Compilation: public StackObj { public: // creation Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method, - int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive); + int osr_bci, BufferBlob* buffer_blob, bool install_code, DirectiveSet* directive); ~Compilation(); @@ -150,6 +151,7 @@ class Compilation: public StackObj { CodeOffsets* offsets() { return &_offsets; } Arena* arena() { return _arena; } bool has_access_indexed() { return _has_access_indexed; } + bool should_install_code() { return _install_code && InstallMethods; } // Instruction ids int get_next_id() { return _next_id++; } diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp index aa6727c1d5f..dbfcc610daf 100644 --- a/src/hotspot/share/c1/c1_Compiler.cpp +++ b/src/hotspot/share/c1/c1_Compiler.cpp @@ -235,7 +235,7 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) { return true; } -void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci, DirectiveSet* directive) { +void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci, bool install_code, DirectiveSet* directive) { BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob(); assert(buffer_blob != NULL, "Must exist"); // invoke compilation @@ -244,7 +244,7 @@ void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci, Direc // of Compilation to occur before we release the any // competing compiler thread ResourceMark rm; - Compilation c(this, env, method, entry_bci, buffer_blob, directive); + Compilation c(this, env, method, entry_bci, buffer_blob, install_code, directive); } } diff --git a/src/hotspot/share/c1/c1_Compiler.hpp b/src/hotspot/share/c1/c1_Compiler.hpp index eda25290316..880a5a63fec 100644 --- a/src/hotspot/share/c1/c1_Compiler.hpp +++ b/src/hotspot/share/c1/c1_Compiler.hpp @@ -51,7 +51,7 @@ class Compiler: public AbstractCompiler { virtual void initialize(); // Compilation entry point for methods - virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive); + virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, bool install_code, DirectiveSet* directive); // Print compilation timers and statistics virtual void print_timers(); diff --git a/src/hotspot/share/ci/ciEnv.hpp b/src/hotspot/share/ci/ciEnv.hpp index d28fd5a14df..dd11ed03350 100644 --- a/src/hotspot/share/ci/ciEnv.hpp +++ b/src/hotspot/share/ci/ciEnv.hpp @@ -27,7 +27,6 @@ #include "ci/ciClassList.hpp" #include "ci/ciObjectFactory.hpp" -#include "classfile/systemDictionary.hpp" #include "code/debugInfoRec.hpp" #include "code/dependencies.hpp" #include "code/exceptionHandlerTable.hpp" diff --git a/src/hotspot/share/ci/ciMethod.hpp b/src/hotspot/share/ci/ciMethod.hpp index 973c47ef880..c5726aedc99 100644 --- a/src/hotspot/share/ci/ciMethod.hpp +++ b/src/hotspot/share/ci/ciMethod.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ class MethodLiveness; class Arena; class BCEscapeAnalyzer; class InlineTree; +class xmlStream; // Whether profiling found an oop to be always, never or sometimes // null diff --git a/src/hotspot/share/classfile/packageEntry.hpp b/src/hotspot/share/classfile/packageEntry.hpp index 1cb982160e6..ee2bfe86a6f 100644 --- a/src/hotspot/share/classfile/packageEntry.hpp +++ b/src/hotspot/share/classfile/packageEntry.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "classfile/moduleEntry.hpp" #include "oops/symbol.hpp" +#include "runtime/atomic.hpp" #include "utilities/growableArray.hpp" #include "utilities/hashtable.hpp" #include "utilities/macros.hpp" @@ -114,6 +115,8 @@ class PackageEntry : public HashtableEntry { // Initial size of a package entry's list of qualified exports. enum {QUAL_EXP_SIZE = 43}; + // a bit map indicating which CDS classpath entries have defined classes in this package. + volatile int _defined_by_cds_in_class_path; public: void init() { _module = NULL; @@ -121,6 +124,7 @@ class PackageEntry : public HashtableEntry { _classpath_index = -1; _must_walk_exports = false; _qualified_exports = NULL; + _defined_by_cds_in_class_path = 0; } // package name @@ -212,6 +216,24 @@ class PackageEntry : public HashtableEntry { void print(outputStream* st = tty); void verify(); + + static int max_index_for_defined_in_class_path() { + return sizeof(int) * BitsPerByte; + } + + bool is_defined_by_cds_in_class_path(int idx) const { + assert(idx < max_index_for_defined_in_class_path(), "sanity"); + return((Atomic::load(&_defined_by_cds_in_class_path) & ((int)1 << idx)) != 0); + } + void set_defined_by_cds_in_class_path(int idx) { + assert(idx < max_index_for_defined_in_class_path(), "sanity"); + int old_val = 0; + int new_val = 0; + do { + old_val = Atomic::load(&_defined_by_cds_in_class_path); + new_val = old_val | ((int)1 << idx); + } while (Atomic::cmpxchg(&_defined_by_cds_in_class_path, old_val, new_val) != old_val); + } }; // The PackageEntryTable is a Hashtable containing a list of all packages defined diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 4d5cda155a6..719ce6b7f92 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -872,7 +872,19 @@ Handle SystemDictionaryShared::init_security_info(Handle class_loader, InstanceK // the corresponding SystemDictionaryShared::get_shared_xxx() function. Handle manifest = get_shared_jar_manifest(index, CHECK_(pd)); Handle url = get_shared_jar_url(index, CHECK_(pd)); - define_shared_package(class_name, class_loader, manifest, url, CHECK_(pd)); + int index_offset = index - ClassLoaderExt::app_class_paths_start_index(); + if (index_offset < PackageEntry::max_index_for_defined_in_class_path()) { + if (pkg_entry == NULL || !pkg_entry->is_defined_by_cds_in_class_path(index_offset)) { + // define_shared_package only needs to be called once for each package in a jar specified + // in the shared class path. + define_shared_package(class_name, class_loader, manifest, url, CHECK_(pd)); + if (pkg_entry != NULL) { + pkg_entry->set_defined_by_cds_in_class_path(index_offset); + } + } + } else { + define_shared_package(class_name, class_loader, manifest, url, CHECK_(pd)); + } pd = get_shared_protection_domain(class_loader, index, url, CHECK_(pd)); } } diff --git a/src/hotspot/share/code/dependencies.hpp b/src/hotspot/share/code/dependencies.hpp index 4396fdc52e3..960be1c3c71 100644 --- a/src/hotspot/share/code/dependencies.hpp +++ b/src/hotspot/share/code/dependencies.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ #include "ci/ciKlass.hpp" #include "ci/ciMethod.hpp" #include "ci/ciMethodHandle.hpp" -#include "classfile/systemDictionary.hpp" #include "code/compressedStream.hpp" #include "code/nmethod.hpp" #include "memory/resourceArea.hpp" diff --git a/src/hotspot/share/code/icBuffer.hpp b/src/hotspot/share/code/icBuffer.hpp index 5289738fa0d..a15420e8ddc 100644 --- a/src/hotspot/share/code/icBuffer.hpp +++ b/src/hotspot/share/code/icBuffer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,9 @@ #include "utilities/debug.hpp" #include "utilities/macros.hpp" +class CompiledIC; +class CompiledICHolder; + // // For CompiledIC's: // diff --git a/src/hotspot/share/compiler/abstractCompiler.hpp b/src/hotspot/share/compiler/abstractCompiler.hpp index 6fb8e644caf..922121ec29e 100644 --- a/src/hotspot/share/compiler/abstractCompiler.hpp +++ b/src/hotspot/share/compiler/abstractCompiler.hpp @@ -166,7 +166,7 @@ class AbstractCompiler : public CHeapObj { void set_state (int state); void set_shut_down () { set_state(shut_down); } // Compilation entry point for methods - virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) { + virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, bool install_code, DirectiveSet* directive) { ShouldNotReachHere(); } diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index c221edcf3ba..a1eabd06602 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -1201,7 +1201,7 @@ void CompileBroker::compile_method_base(const methodHandle& method, // Don't allow blocking compilation requests if we are in JVMCIRuntime::shutdown // to avoid deadlock between compiler thread(s) and threads run at shutdown // such as the DestroyJavaVM thread. - if (JVMCI::shutdown_called()) { + if (JVMCI::in_shutdown()) { blocking = false; } } @@ -2150,16 +2150,22 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) { TraceTime t1("compilation", &time); EventCompilation event; JVMCICompileState compile_state(task); + JVMCIRuntime *runtime = NULL; - // Skip redefined methods - if (compile_state.target_method_is_old()) { + if (JVMCI::in_shutdown()) { + failure_reason = "in JVMCI shutdown"; + retry_message = "not retryable"; + compilable = ciEnv::MethodCompilable_never; + } else if (compile_state.target_method_is_old()) { + // Skip redefined methods failure_reason = "redefined method"; retry_message = "not retryable"; compilable = ciEnv::MethodCompilable_never; } else { JVMCIEnv env(thread, &compile_state, __FILE__, __LINE__); methodHandle method(thread, target_handle); - env.runtime()->compile_method(&env, jvmci, method, osr_bci); + runtime = env.runtime(); + runtime->compile_method(&env, jvmci, method, osr_bci); failure_reason = compile_state.failure_reason(); failure_reason_on_C_heap = compile_state.failure_reason_on_C_heap(); @@ -2217,7 +2223,15 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) { locker.wait(); } } - comp->compile_method(&ci_env, target, osr_bci, directive); + comp->compile_method(&ci_env, target, osr_bci, true, directive); + + /* Repeat compilation without installing code for profiling purposes */ + int repeat_compilation_count = directive->RepeatCompilationOption; + while (repeat_compilation_count > 0) { + task->print_ul("NO CODE INSTALLED"); + comp->compile_method(&ci_env, target, osr_bci, false , directive); + repeat_compilation_count--; + } } if (!ci_env.failing() && task->code() == NULL) { diff --git a/src/hotspot/share/compiler/compilerDirectives.hpp b/src/hotspot/share/compiler/compilerDirectives.hpp index 8908c0ee800..a04c13ea061 100644 --- a/src/hotspot/share/compiler/compilerDirectives.hpp +++ b/src/hotspot/share/compiler/compilerDirectives.hpp @@ -48,7 +48,8 @@ cflags(DumpInline, bool, false, DumpInline) \ cflags(CompilerDirectivesIgnoreCompileCommands, bool, CompilerDirectivesIgnoreCompileCommands, X) \ cflags(DisableIntrinsic, ccstrlist, DisableIntrinsic, DisableIntrinsic) \ - cflags(ControlIntrinsic, ccstrlist, ControlIntrinsic, ControlIntrinsic) + cflags(ControlIntrinsic, ccstrlist, ControlIntrinsic, ControlIntrinsic) \ + cflags(RepeatCompilation, intx, RepeatCompilation, RepeatCompilation) #ifdef COMPILER1 #define compilerdirectives_c1_flags(cflags) @@ -64,11 +65,11 @@ NOT_PRODUCT(cflags(TraceOptoPipelining, bool, TraceOptoPipelining, TraceOptoPipelining)) \ NOT_PRODUCT(cflags(TraceOptoOutput, bool, TraceOptoOutput, TraceOptoOutput)) \ NOT_PRODUCT(cflags(PrintIdeal, bool, PrintIdeal, PrintIdeal)) \ -NOT_PRODUCT(cflags(IGVPrintLevel, intx, PrintIdealGraphLevel, IGVPrintLevel)) \ cflags(TraceSpilling, bool, TraceSpilling, TraceSpilling) \ cflags(Vectorize, bool, false, Vectorize) \ - cflags(VectorizeDebug, uintx, 0, VectorizeDebug) \ cflags(CloneMapDebug, bool, false, CloneMapDebug) \ +NOT_PRODUCT(cflags(IGVPrintLevel, intx, PrintIdealGraphLevel, IGVPrintLevel)) \ + cflags(VectorizeDebug, uintx, 0, VectorizeDebug) \ cflags(MaxNodeLimit, intx, MaxNodeLimit, MaxNodeLimit) #else #define compilerdirectives_c2_flags(cflags) diff --git a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp index 259126dd955..e074dcf60c7 100644 --- a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp +++ b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/javaClasses.hpp" #include "gc/g1/c2/g1BarrierSetC2.hpp" #include "gc/g1/g1BarrierSet.hpp" #include "gc/g1/g1BarrierSetRuntime.hpp" diff --git a/src/hotspot/share/gc/g1/g1Analytics.cpp b/src/hotspot/share/gc/g1/g1Analytics.cpp index c817d27a899..853de98da24 100644 --- a/src/hotspot/share/gc/g1/g1Analytics.cpp +++ b/src/hotspot/share/gc/g1/g1Analytics.cpp @@ -224,11 +224,7 @@ void G1Analytics::report_rs_length(double rs_length) { } double G1Analytics::predict_alloc_rate_ms() const { - if (enough_samples_available(_alloc_rate_ms_seq)) { - return predict_zero_bounded(_alloc_rate_ms_seq); - } else { - return 0.0; - } + return predict_zero_bounded(_alloc_rate_ms_seq); } double G1Analytics::predict_concurrent_refine_rate_ms() const { diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index e447be4e7b3..d62e897af1b 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -46,7 +46,6 @@ #include "gc/shared/gcPolicyCounters.hpp" #include "logging/log.hpp" #include "runtime/arguments.hpp" -#include "runtime/globals.hpp" #include "runtime/java.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/debug.hpp" @@ -62,8 +61,8 @@ G1Policy::G1Policy(STWGCTimer* gc_timer) : _policy_counters(new GCPolicyCounters("GarbageFirst", 1, 2)), _full_collection_start_sec(0.0), _collection_pause_end_millis(os::javaTimeNanos() / NANOSECS_PER_MILLISEC), - _young_list_desired_length(0), _young_list_target_length(0), + _young_list_fixed_length(0), _young_list_max_length(0), _eden_surv_rate_group(new G1SurvRateGroup()), _survivor_surv_rate_group(new G1SurvRateGroup()), @@ -108,11 +107,14 @@ void G1Policy::init(G1CollectedHeap* g1h, G1CollectionSet* collection_set) { assert(Heap_lock->owned_by_self(), "Locking discipline."); + if (!use_adaptive_young_list_length()) { + _young_list_fixed_length = _young_gen_sizer->min_desired_young_length(); + } _young_gen_sizer->adjust_max_new_size(_g1h->max_expandable_regions()); _free_regions_at_end_of_collection = _g1h->num_free_regions(); - update_young_length_bounds(); + update_young_list_max_and_target_length(); // We may immediately start allocating regions and placing them on the // collection set list. Initialize the per-collection set info _collection_set->start_incremental_building(); @@ -187,254 +189,158 @@ void G1Policy::record_new_heap_size(uint new_number_of_regions) { _ihop_control->update_target_occupancy(new_number_of_regions * HeapRegion::GrainBytes); } -uint G1Policy::calculate_desired_eden_length_by_mmu() const { - // One could argue that any useful eden length to keep any MMU would be 1, but - // in theory this is possible. Other constraints enforce a minimum eden of 1 - // anyway. +uint G1Policy::calculate_young_list_desired_min_length(uint base_min_length) const { uint desired_min_length = 0; if (use_adaptive_young_list_length()) { - double now_sec = os::elapsedTime(); - double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0; - double alloc_rate_ms = _analytics->predict_alloc_rate_ms(); - desired_min_length = (uint) ceil(alloc_rate_ms * when_ms); + if (_analytics->num_alloc_rate_ms() > 3) { + double now_sec = os::elapsedTime(); + double when_ms = _mmu_tracker->when_max_gc_sec(now_sec) * 1000.0; + double alloc_rate_ms = _analytics->predict_alloc_rate_ms(); + desired_min_length = (uint) ceil(alloc_rate_ms * when_ms); + } else { + // otherwise we don't have enough info to make the prediction + } } - return desired_min_length; -} - -void G1Policy::update_young_length_bounds() { - update_young_length_bounds(_analytics->predict_rs_length()); -} - -void G1Policy::update_young_length_bounds(size_t rs_length) { - _young_list_desired_length = calculate_young_desired_length(rs_length); - _young_list_target_length = calculate_young_target_length(_young_list_desired_length); - _young_list_max_length = calculate_young_max_length(_young_list_target_length); - - log_debug(gc,ergo,heap)("Young list lengths: desired: %u, target: %u, max: %u", - _young_list_desired_length, - _young_list_target_length, - _young_list_max_length); -} - -// Calculates desired young gen length. It is calculated from: -// -// - sizer min/max bounds on young gen -// - pause time goal for whole young gen evacuation -// - MMU goal influencing eden to make GCs spaced apart. -// - a minimum one eden region length. -// -// We may enter with already allocated eden and survivor regions, that may be -// higher than the maximum, or the above goals may result in a desired value -// smaller than are already allocated. -// The main reason is revising young length, with our without the GCLocker being -// active. -// -uint G1Policy::calculate_young_desired_length(size_t rs_length) const { - uint min_young_length_by_sizer = _young_gen_sizer->min_desired_young_length(); - uint max_young_length_by_sizer = _young_gen_sizer->max_desired_young_length(); - - assert(min_young_length_by_sizer >= 1, "invariant"); - assert(max_young_length_by_sizer >= min_young_length_by_sizer, "invariant"); - - // Absolute minimum eden length. - // Enforcing a minimum eden length helps at startup when the predictors are not - // yet trained on the application to avoid unnecessary (but very short) full gcs - // on very small (initial) heaps. - uint const MinDesiredEdenLength = 1; + desired_min_length += base_min_length; + // make sure we don't go below any user-defined minimum bound + return MAX2(_young_gen_sizer->min_desired_young_length(), desired_min_length); +} + +uint G1Policy::calculate_young_list_desired_max_length() const { + // Here, we might want to also take into account any additional + // constraints (i.e., user-defined minimum bound). Currently, we + // effectively don't set this bound. + return _young_gen_sizer->max_desired_young_length(); +} + +uint G1Policy::update_young_list_max_and_target_length() { + return update_young_list_max_and_target_length(_analytics->predict_rs_length()); +} + +uint G1Policy::update_young_list_max_and_target_length(size_t rs_length) { + uint unbounded_target_length = update_young_list_target_length(rs_length); + update_max_gc_locker_expansion(); + return unbounded_target_length; +} + +uint G1Policy::update_young_list_target_length(size_t rs_length) { + YoungTargetLengths young_lengths = young_list_target_lengths(rs_length); + _young_list_target_length = young_lengths.first; + + return young_lengths.second; +} + +G1Policy::YoungTargetLengths G1Policy::young_list_target_lengths(size_t rs_length) const { + YoungTargetLengths result; // Calculate the absolute and desired min bounds first. - // This is how many survivor regions we already have. - const uint survivor_length = _g1h->survivor_regions_count(); - // Size of the already allocated young gen. - const uint allocated_young_length = _g1h->young_regions_count(); - // This is the absolute minimum young length that we can return. Ensure that we - // don't go below any user-defined minimum bound; but we might have already - // allocated more than that for reasons. In this case, use that. - uint absolute_min_young_length = MAX2(allocated_young_length, min_young_length_by_sizer); - // Calculate the absolute max bounds. After evac failure or when revising the - // young length we might have exceeded absolute min length or absolute_max_length, - // so adjust the result accordingly. - uint absolute_max_young_length = MAX2(max_young_length_by_sizer, absolute_min_young_length); - - uint desired_eden_length_by_mmu = 0; - uint desired_eden_length_by_pause = 0; - uint desired_eden_length_before_mixed = 0; - - uint desired_young_length = 0; - if (use_adaptive_young_list_length()) { - desired_eden_length_by_mmu = calculate_desired_eden_length_by_mmu(); + // This is how many young regions we already have (currently: the survivors). + const uint base_min_length = _g1h->survivor_regions_count(); + uint desired_min_length = calculate_young_list_desired_min_length(base_min_length); + // This is the absolute minimum young length. Ensure that we + // will at least have one eden region available for allocation. + uint absolute_min_length = base_min_length + MAX2(_g1h->eden_regions_count(), (uint)1); + // If we shrank the young list target it should not shrink below the current size. + desired_min_length = MAX2(desired_min_length, absolute_min_length); + // Calculate the absolute and desired max bounds. - const size_t pending_cards = _analytics->predict_pending_cards(); - double survivor_base_time_ms = predict_base_elapsed_time_ms(pending_cards, rs_length); + uint desired_max_length = calculate_young_list_desired_max_length(); - if (!next_gc_should_be_mixed(NULL, NULL)) { - desired_eden_length_by_pause = - calculate_desired_eden_length_by_pause(survivor_base_time_ms, - absolute_min_young_length - survivor_length, - absolute_max_young_length - survivor_length); + uint young_list_target_length = 0; + if (use_adaptive_young_list_length()) { + if (collector_state()->in_young_only_phase()) { + young_list_target_length = + calculate_young_list_target_length(rs_length, + base_min_length, + desired_min_length, + desired_max_length); } else { - desired_eden_length_before_mixed = - calculate_desired_eden_length_before_mixed(survivor_base_time_ms, - absolute_min_young_length - survivor_length, - absolute_max_young_length - survivor_length); + // Don't calculate anything and let the code below bound it to + // the desired_min_length, i.e., do the next GC as soon as + // possible to maximize how many old regions we can add to it. } - // Above either sets desired_eden_length_by_pause or desired_eden_length_before_mixed, - // the other is zero. Use the one that has been set below. - uint desired_eden_length = MAX2(desired_eden_length_by_pause, - desired_eden_length_before_mixed); - - // Finally incorporate MMU concerns; assume that it overrides the pause time - // goal, as the default value has been chosen to effectively disable it. - // Also request at least one eden region, see above for reasons. - desired_eden_length = MAX3(desired_eden_length, - desired_eden_length_by_mmu, - MinDesiredEdenLength); - - desired_young_length = desired_eden_length + survivor_length; } else { // The user asked for a fixed young gen so we'll fix the young gen // whether the next GC is young or mixed. - desired_young_length = min_young_length_by_sizer; + young_list_target_length = _young_list_fixed_length; } - // Clamp to absolute min/max after we determined desired lengths. - desired_young_length = clamp(desired_young_length, absolute_min_young_length, absolute_max_young_length); - - log_trace(gc, ergo, heap)("Young desired length %u " - "survivor length %u " - "allocated young length %u " - "absolute min young length %u " - "absolute max young length %u " - "desired eden length by mmu %u " - "desired eden length by pause %u " - "desired eden length before mixed %u" - "desired eden length by default %u", - desired_young_length, survivor_length, - allocated_young_length, absolute_min_young_length, - absolute_max_young_length, desired_eden_length_by_mmu, - desired_eden_length_by_pause, - desired_eden_length_before_mixed, - MinDesiredEdenLength); - - assert(desired_young_length >= allocated_young_length, "must be"); - return desired_young_length; -} - -// Limit the desired (wished) young length by current free regions. If the request -// can be satisfied without using up reserve regions, do so, otherwise eat into -// the reserve, giving away at most what the heap sizer allows. -uint G1Policy::calculate_young_target_length(uint desired_young_length) const { - uint allocated_young_length = _g1h->young_regions_count(); - - uint receiving_additional_eden; - if (allocated_young_length >= desired_young_length) { - // Already used up all we actually want (may happen as G1 revises the - // young list length concurrently, or caused by gclocker). Do not allow more, - // potentially resulting in GC. - receiving_additional_eden = 0; - log_trace(gc, ergo, heap)("Young target length: Already used up desired young %u allocated %u", - desired_young_length, - allocated_young_length); - } else { - // Now look at how many free regions are there currently, and the heap reserve. - // We will try our best not to "eat" into the reserve as long as we can. If we - // do, we at most eat the sizer's minimum regions into the reserve or half the - // reserve rounded up (if possible; this is an arbitrary value). - - uint max_to_eat_into_reserve = MIN2(_young_gen_sizer->min_desired_young_length(), - (_reserve_regions + 1) / 2); - - log_trace(gc, ergo, heap)("Young target length: Common " - "free regions at end of collection %u " - "desired young length %u " - "reserve region %u " - "max to eat into reserve %u", - _free_regions_at_end_of_collection, - desired_young_length, - _reserve_regions, - max_to_eat_into_reserve); - - if (_free_regions_at_end_of_collection <= _reserve_regions) { - // Fully eat (or already eating) into the reserve, hand back at most absolute_min_length regions. - uint receiving_young = MIN3(_free_regions_at_end_of_collection, - desired_young_length, - max_to_eat_into_reserve); - // We could already have allocated more regions than what we could get - // above. - receiving_additional_eden = allocated_young_length < receiving_young ? - receiving_young - allocated_young_length : 0; - - log_trace(gc, ergo, heap)("Young target length: Fully eat into reserve " - "receiving young %u receiving additional eden %u", - receiving_young, - receiving_additional_eden); - } else if (_free_regions_at_end_of_collection < (desired_young_length + _reserve_regions)) { - // Partially eat into the reserve, at most max_to_eat_into_reserve regions. - uint free_outside_reserve = _free_regions_at_end_of_collection - _reserve_regions; - assert(free_outside_reserve < desired_young_length, - "must be %u %u", - free_outside_reserve, desired_young_length); - - uint receiving_within_reserve = MIN2(desired_young_length - free_outside_reserve, - max_to_eat_into_reserve); - uint receiving_young = free_outside_reserve + receiving_within_reserve; - // Again, we could have already allocated more than we could get. - receiving_additional_eden = allocated_young_length < receiving_young ? - receiving_young - allocated_young_length : 0; - - log_trace(gc, ergo, heap)("Young target length: Partially eat into reserve " - "free outside reserve %u " - "receiving within reserve %u " - "receiving young %u " - "receiving additional eden %u", - free_outside_reserve, receiving_within_reserve, - receiving_young, receiving_additional_eden); - } else { - // No need to use the reserve. - receiving_additional_eden = desired_young_length - allocated_young_length; - log_trace(gc, ergo, heap)("Young target length: No need to use reserve " - "receiving additional eden %u", - receiving_additional_eden); - } + + result.second = young_list_target_length; + + // We will try our best not to "eat" into the reserve. + uint absolute_max_length = 0; + if (_free_regions_at_end_of_collection > _reserve_regions) { + absolute_max_length = _free_regions_at_end_of_collection - _reserve_regions; + } + if (desired_max_length > absolute_max_length) { + desired_max_length = absolute_max_length; } - uint target_young_length = allocated_young_length + receiving_additional_eden; + // Make sure we don't go over the desired max length, nor under the + // desired min length. In case they clash, desired_min_length wins + // which is why that test is second. + if (young_list_target_length > desired_max_length) { + young_list_target_length = desired_max_length; + } + if (young_list_target_length < desired_min_length) { + young_list_target_length = desired_min_length; + } - assert(target_young_length >= allocated_young_length, "must be"); + assert(young_list_target_length > base_min_length, + "we should be able to allocate at least one eden region"); + assert(young_list_target_length >= absolute_min_length, "post-condition"); - log_trace(gc, ergo, heap)("Young target length: " - "young target length %u " - "allocated young length %u " - "received additional eden %u", - target_young_length, allocated_young_length, - receiving_additional_eden); - return target_young_length; + result.first = young_list_target_length; + return result; } -uint G1Policy::calculate_desired_eden_length_by_pause(double base_time_ms, - uint min_eden_length, - uint max_eden_length) const { +uint G1Policy::calculate_young_list_target_length(size_t rs_length, + uint base_min_length, + uint desired_min_length, + uint desired_max_length) const { assert(use_adaptive_young_list_length(), "pre-condition"); + assert(collector_state()->in_young_only_phase(), "only call this for young GCs"); + + // In case some edge-condition makes the desired max length too small... + if (desired_max_length <= desired_min_length) { + return desired_min_length; + } - assert(min_eden_length <= max_eden_length, "must be %u %u", min_eden_length, max_eden_length); + // We'll adjust min_young_length and max_young_length not to include + // the already allocated young regions (i.e., so they reflect the + // min and max eden regions we'll allocate). The base_min_length + // will be reflected in the predictions by the + // survivor_regions_evac_time prediction. + assert(desired_min_length > base_min_length, "invariant"); + uint min_young_length = desired_min_length - base_min_length; + assert(desired_max_length > base_min_length, "invariant"); + uint max_young_length = desired_max_length - base_min_length; + + const double target_pause_time_ms = _mmu_tracker->max_gc_time() * 1000.0; + const size_t pending_cards = _analytics->predict_pending_cards(); + const double base_time_ms = predict_base_elapsed_time_ms(pending_cards, rs_length); + const uint available_free_regions = _free_regions_at_end_of_collection; + const uint base_free_regions = + available_free_regions > _reserve_regions ? available_free_regions - _reserve_regions : 0; // Here, we will make sure that the shortest young length that // makes sense fits within the target pause time. G1YoungLengthPredictor p(base_time_ms, - _free_regions_at_end_of_collection, - _mmu_tracker->max_gc_time() * 1000.0, + base_free_regions, + target_pause_time_ms, this); - if (p.will_fit(min_eden_length)) { + if (p.will_fit(min_young_length)) { // The shortest young length will fit into the target pause time; // we'll now check whether the absolute maximum number of young // regions will fit in the target pause time. If not, we'll do // a binary search between min_young_length and max_young_length. - if (p.will_fit(max_eden_length)) { + if (p.will_fit(max_young_length)) { // The maximum young length will fit into the target pause time. // We are done so set min young length to the maximum length (as // the result is assumed to be returned in min_young_length). - min_eden_length = max_eden_length; + min_young_length = max_young_length; } else { // The maximum possible number of young regions will not fit within // the target pause time so we'll search for the optimal @@ -451,56 +357,37 @@ uint G1Policy::calculate_desired_eden_length_by_pause(double base_time_ms, // does, it becomes the new min. If it doesn't, it becomes // the new max. This way we maintain the loop invariants. - assert(min_eden_length < max_eden_length, "invariant"); - uint diff = (max_eden_length - min_eden_length) / 2; + assert(min_young_length < max_young_length, "invariant"); + uint diff = (max_young_length - min_young_length) / 2; while (diff > 0) { - uint eden_length = min_eden_length + diff; - if (p.will_fit(eden_length)) { - min_eden_length = eden_length; + uint young_length = min_young_length + diff; + if (p.will_fit(young_length)) { + min_young_length = young_length; } else { - max_eden_length = eden_length; + max_young_length = young_length; } - assert(min_eden_length < max_eden_length, "invariant"); - diff = (max_eden_length - min_eden_length) / 2; + assert(min_young_length < max_young_length, "invariant"); + diff = (max_young_length - min_young_length) / 2; } // The results is min_young_length which, according to the // loop invariants, should fit within the target pause time. // These are the post-conditions of the binary search above: - assert(min_eden_length < max_eden_length, - "otherwise we should have discovered that max_eden_length " + assert(min_young_length < max_young_length, + "otherwise we should have discovered that max_young_length " "fits into the pause target and not done the binary search"); - assert(p.will_fit(min_eden_length), - "min_eden_length, the result of the binary search, should " + assert(p.will_fit(min_young_length), + "min_young_length, the result of the binary search, should " "fit into the pause target"); - assert(!p.will_fit(min_eden_length + 1), - "min_eden_length, the result of the binary search, should be " + assert(!p.will_fit(min_young_length + 1), + "min_young_length, the result of the binary search, should be " "optimal, so no larger length should fit into the pause target"); } } else { // Even the minimum length doesn't fit into the pause time // target, return it as the result nevertheless. } - return min_eden_length; -} - -uint G1Policy::calculate_desired_eden_length_before_mixed(double survivor_base_time_ms, - uint min_eden_length, - uint max_eden_length) const { - G1CollectionSetCandidates* candidates = _collection_set->candidates(); - - uint min_old_regions_end = MIN2(candidates->cur_idx() + calc_min_old_cset_length(), candidates->num_regions()); - double predicted_region_evac_time_ms = survivor_base_time_ms; - for (uint i = candidates->cur_idx(); i < min_old_regions_end; i++) { - HeapRegion* r = candidates->at(i); - predicted_region_evac_time_ms += predict_region_total_time_ms(r, false); - } - uint desired_eden_length_by_min_cset_length = - calculate_desired_eden_length_by_pause(predicted_region_evac_time_ms, - min_eden_length, - max_eden_length); - - return desired_eden_length_by_min_cset_length; + return base_min_length + min_young_length; } double G1Policy::predict_survivor_regions_evac_time() const { @@ -521,7 +408,8 @@ void G1Policy::revise_young_list_target_length_if_necessary(size_t rs_length) { // add 10% to avoid having to recalculate often size_t rs_length_prediction = rs_length * 1100 / 1000; update_rs_length_prediction(rs_length_prediction); - update_young_length_bounds(rs_length_prediction); + + update_young_list_max_and_target_length(rs_length_prediction); } } @@ -569,7 +457,7 @@ void G1Policy::record_full_collection_end() { _free_regions_at_end_of_collection = _g1h->num_free_regions(); _survivor_surv_rate_group->reset(); - update_young_length_bounds(); + update_young_list_max_and_target_length(); update_rs_length_prediction(); _old_gen_alloc_tracker.reset_after_full_gc(); @@ -899,11 +787,16 @@ void G1Policy::record_collection_pause_end(double pause_time_ms) { // Do not update dynamic IHOP due to G1 periodic collection as it is highly likely // that in this case we are not running in a "normal" operating mode. if (_g1h->gc_cause() != GCCause::_g1_periodic_collection) { - update_young_length_bounds(); + // IHOP control wants to know the expected young gen length if it were not + // restrained by the heap reserve. Using the actual length would make the + // prediction too small and the limit the young gen every time we get to the + // predicted target occupancy. + size_t last_unrestrained_young_length = update_young_list_max_and_target_length(); _old_gen_alloc_tracker.reset_after_young_gc(app_time_ms / 1000.0); update_ihop_prediction(_old_gen_alloc_tracker.last_cycle_duration(), _old_gen_alloc_tracker.last_cycle_old_bytes(), + last_unrestrained_young_length * HeapRegion::GrainBytes, this_pause_was_young_only); _ihop_control->send_trace_event(_g1h->gc_tracer_stw()); @@ -953,6 +846,7 @@ G1IHOPControl* G1Policy::create_ihop_control(const G1Predictions* predictor){ void G1Policy::update_ihop_prediction(double mutator_time_s, size_t mutator_alloc_bytes, + size_t young_gen_size, bool this_gc_was_young_only) { // Always try to update IHOP prediction. Even evacuation failures give information // about e.g. whether to start IHOP earlier next time. @@ -980,11 +874,6 @@ void G1Policy::update_ihop_prediction(double mutator_time_s, // marking, which makes any prediction useless. This increases the accuracy of the // prediction. if (this_gc_was_young_only && mutator_time_s > min_valid_time) { - // IHOP control wants to know the expected young gen length if it were not - // restrained by the heap reserve. Using the actual length would make the - // prediction too small and the limit the young gen every time we get to the - // predicted target occupancy. - size_t young_gen_size = young_list_desired_length() * HeapRegion::GrainBytes; _ihop_control->update_allocation_info(mutator_time_s, mutator_alloc_bytes, young_gen_size); report = true; } @@ -1091,7 +980,7 @@ void G1Policy::print_age_table() { _survivors_age_table.print_age_table(_tenuring_threshold); } -uint G1Policy::calculate_young_max_length(uint target_young_length) const { +void G1Policy::update_max_gc_locker_expansion() { uint expansion_region_num = 0; if (GCLockerEdenExpansionPercent > 0) { double perc = (double) GCLockerEdenExpansionPercent / 100.0; @@ -1102,9 +991,8 @@ uint G1Policy::calculate_young_max_length(uint target_young_length) const { } else { assert(expansion_region_num == 0, "sanity"); } - uint max_length = target_young_length + expansion_region_num; - assert(target_young_length <= max_length, "post-condition"); - return max_length; + _young_list_max_length = _young_list_target_length + expansion_region_num; + assert(_young_list_target_length <= _young_list_max_length, "post-condition"); } // Calculates survivor space parameters. @@ -1313,10 +1201,8 @@ bool G1Policy::next_gc_should_be_mixed(const char* true_action_str, const char* false_action_str) const { G1CollectionSetCandidates* candidates = _collection_set->candidates(); - if (candidates == NULL || candidates->is_empty()) { - if (false_action_str != NULL) { - log_debug(gc, ergo)("%s (candidate old regions not available)", false_action_str); - } + if (candidates->is_empty()) { + log_debug(gc, ergo)("%s (candidate old regions not available)", false_action_str); return false; } @@ -1325,16 +1211,12 @@ bool G1Policy::next_gc_should_be_mixed(const char* true_action_str, double reclaimable_percent = reclaimable_bytes_percent(reclaimable_bytes); double threshold = (double) G1HeapWastePercent; if (reclaimable_percent <= threshold) { - if (false_action_str != NULL) { - log_debug(gc, ergo)("%s (reclaimable percentage not over threshold). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT, - false_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent); - } + log_debug(gc, ergo)("%s (reclaimable percentage not over threshold). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT, + false_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent); return false; } - if (true_action_str != NULL) { - log_debug(gc, ergo)("%s (candidate old regions available). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT, - true_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent); - } + log_debug(gc, ergo)("%s (candidate old regions available). candidate old regions: %u reclaimable: " SIZE_FORMAT " (%1.2f) threshold: " UINTX_FORMAT, + true_action_str, candidates->num_remaining(), reclaimable_bytes, reclaimable_percent, G1HeapWastePercent); return true; } diff --git a/src/hotspot/share/gc/g1/g1Policy.hpp b/src/hotspot/share/gc/g1/g1Policy.hpp index 9784fd4e10e..473ebbac392 100644 --- a/src/hotspot/share/gc/g1/g1Policy.hpp +++ b/src/hotspot/share/gc/g1/g1Policy.hpp @@ -60,6 +60,7 @@ class G1Policy: public CHeapObj { // Update the IHOP control with necessary statistics. void update_ihop_prediction(double mutator_time_s, size_t mutator_alloc_bytes, + size_t young_gen_size, bool this_gc_was_young_only); void report_ihop_statistics(); @@ -75,8 +76,8 @@ class G1Policy: public CHeapObj { jlong _collection_pause_end_millis; - uint _young_list_desired_length; uint _young_list_target_length; + uint _young_list_fixed_length; // The max number of regions we can extend the eden by while the GC // locker is active. This should be >= _young_list_target_length; @@ -169,10 +170,6 @@ class G1Policy: public CHeapObj { private: G1CollectionSet* _collection_set; - - bool next_gc_should_be_mixed(const char* true_action_str, - const char* false_action_str) const; - double average_time_ms(G1GCPhaseTimes::GCParPhases phase) const; double other_time_ms(double pause_time_ms) const; @@ -192,38 +189,44 @@ class G1Policy: public CHeapObj { double _mark_remark_start_sec; double _mark_cleanup_start_sec; - // Updates the internal young gen maximum and target and desired lengths. - // If no rs_length parameter is passed, predict the RS length using the - // prediction model, otherwise use the given rs_length as the prediction. - void update_young_length_bounds(); - void update_young_length_bounds(size_t rs_length); - - // Calculate and return the minimum desired eden length based on the MMU target. - uint calculate_desired_eden_length_by_mmu() const; - - // Calculate and return the desired eden length that can fit into the pause time goal. - // The parameters are: rs_length represents the prediction of how large the - // young RSet lengths will be, min_eden_length and max_eden_length are the bounds - // (inclusive) within eden can grow. - uint calculate_desired_eden_length_by_pause(double base_time_ms, - uint min_eden_length, - uint max_eden_length) const; - - // Calculates the desired eden length before mixed gc so that after adding the - // minimum amount of old gen regions from the collection set, the eden fits into - // the pause time goal. - uint calculate_desired_eden_length_before_mixed(double survivor_base_time_ms, - uint min_eden_length, - uint max_eden_length) const; - - // Calculate desired young length based on current situation without taking actually - // available free regions into account. - uint calculate_young_desired_length(size_t rs_length) const; - // Limit the given desired young length to available free regions. - uint calculate_young_target_length(uint desired_young_length) const; - // The GCLocker might cause us to need more regions than the target. Calculate - // the maximum number of regions to use in that case. - uint calculate_young_max_length(uint target_young_length) const; + // Updates the internal young list maximum and target lengths. Returns the + // unbounded young list target length. If no rs_length parameter is passed, + // predict the RS length using the prediction model, otherwise use the + // given rs_length as the prediction. + uint update_young_list_max_and_target_length(); + uint update_young_list_max_and_target_length(size_t rs_length); + + // Update the young list target length either by setting it to the + // desired fixed value or by calculating it using G1's pause + // prediction model. + // Returns the unbounded young list target length. + uint update_young_list_target_length(size_t rs_length); + + // Calculate and return the minimum desired young list target + // length. This is the minimum desired young list length according + // to the user's inputs. + uint calculate_young_list_desired_min_length(uint base_min_length) const; + + // Calculate and return the maximum desired young list target + // length. This is the maximum desired young list length according + // to the user's inputs. + uint calculate_young_list_desired_max_length() const; + + // Calculate and return the maximum young list target length that + // can fit into the pause time goal. The parameters are: rs_length + // represent the prediction of how large the young RSet lengths will + // be, base_min_length is the already existing number of regions in + // the young list, min_length and max_length are the desired min and + // max young list length according to the user's inputs. + uint calculate_young_list_target_length(size_t rs_length, + uint base_min_length, + uint desired_min_length, + uint desired_max_length) const; + + // Result of the bounded_young_list_target_length() method, containing both the + // bounded as well as the unbounded young list target lengths in this order. + typedef Pair YoungTargetLengths; + YoungTargetLengths young_list_target_lengths(size_t rs_length) const; void update_rs_length_prediction(); void update_rs_length_prediction(size_t prediction); @@ -332,6 +335,9 @@ class G1Policy: public CHeapObj { void print_phases(); + bool next_gc_should_be_mixed(const char* true_action_str, + const char* false_action_str) const; + // Calculate and return the number of initial and optional old gen regions from // the given collection set candidates and the remaining time. void calculate_old_collection_set_regions(G1CollectionSetCandidates* candidates, @@ -368,7 +374,6 @@ class G1Policy: public CHeapObj { // the initial-mark work and start a marking cycle. void decide_on_conc_mark_initiation(); - uint young_list_desired_length() const { return _young_list_desired_length; } size_t young_list_target_length() const { return _young_list_target_length; } bool should_allocate_mutator_region() const; @@ -429,6 +434,8 @@ class G1Policy: public CHeapObj { void print_age_table(); + void update_max_gc_locker_expansion(); + void update_survivors_policy(); virtual bool force_upgrade_to_full() { diff --git a/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp index 5588a027549..2bd82d7deb4 100644 --- a/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp +++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "c1/c1_Defs.hpp" #include "c1/c1_LIRGenerator.hpp" +#include "classfile/javaClasses.hpp" #include "gc/shared/c1/barrierSetC1.hpp" #include "utilities/macros.hpp" diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp index 46f7ce1c9c1..d3baab50e93 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp @@ -65,9 +65,7 @@ void ShenandoahBarrierSetC2State::add_enqueue_barrier(ShenandoahEnqueueBarrierNo } void ShenandoahBarrierSetC2State::remove_enqueue_barrier(ShenandoahEnqueueBarrierNode * n) { - if (_enqueue_barriers->contains(n)) { - _enqueue_barriers->remove(n); - } + _enqueue_barriers->remove_if_existing(n); } int ShenandoahBarrierSetC2State::load_reference_barriers_count() const { diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index 8d715332241..a1770d245ae 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" +#include "classfile/javaClasses.hpp" #include "gc/shenandoah/c2/shenandoahSupport.hpp" #include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp" #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp b/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp index 0811600b211..2c2bc91cfff 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahInitLogger.cpp @@ -23,7 +23,7 @@ */ #include "precompiled.hpp" -#include "gc/shenandoah/shenandoahHeap.hpp" +#include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" #include "gc/shenandoah/shenandoahInitLogger.hpp" #include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp" diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp index 69a96a20c38..90ca076c6cf 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp @@ -93,9 +93,11 @@ class ShenandoahSerialWeakRoots { JVMTI_ONLY(ShenandoahJVMTIWeakRoot _jvmti_weak_roots;) JFR_ONLY(ShenandoahJFRWeakRoot _jfr_weak_roots;) public: - ShenandoahSerialWeakRoots(ShenandoahPhaseTimings::Phase phase) : - JVMTI_ONLY(_jvmti_weak_roots(phase)) - JFR_ONLY(JVMTI_ONLY(COMMA)_jfr_weak_roots(phase)) {}; + ShenandoahSerialWeakRoots(ShenandoahPhaseTimings::Phase phase) + JVMTI_ONLY(: _jvmti_weak_roots(phase)) + JFR_ONLY(NOT_JVMTI(:) JVMTI_ONLY(COMMA) _jfr_weak_roots(phase)) + {}; + void weak_oops_do(BoolObjectClosure* is_alive, OopClosure* keep_alive, uint worker_id); void weak_oops_do(OopClosure* cl, uint worker_id); }; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp index cdd4ceec9ce..9bc016d6d7d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp @@ -46,6 +46,7 @@ STATIC_ASSERT((static_cast(ShenandoahRootVerifier::AllRoots) + 1) > static_cast(ShenandoahRootVerifier::AllRoots)); ShenandoahRootVerifier::ShenandoahRootVerifier(RootTypes types) : _types(types) { + Threads::change_thread_claim_token(); } void ShenandoahRootVerifier::excludes(RootTypes types) { @@ -138,7 +139,7 @@ void ShenandoahRootVerifier::roots_do(OopClosure* oops) { // Do thread roots the last. This allows verification code to find // any broken objects from those special roots first, not the accidental // dangling reference from the thread root. - Threads::possibly_parallel_oops_do(false, oops, &blobs); + Threads::possibly_parallel_oops_do(true, oops, &blobs); } void ShenandoahRootVerifier::strong_roots_do(OopClosure* oops) { @@ -159,7 +160,7 @@ void ShenandoahRootVerifier::strong_roots_do(OopClosure* oops) { // Do thread roots the last. This allows verification code to find // any broken objects from those special roots first, not the accidental // dangling reference from the thread root. - Threads::possibly_parallel_oops_do(false, oops, &blobs); + Threads::possibly_parallel_oops_do(true, oops, &blobs); } void ShenandoahRootVerifier::serial_weak_roots_do(OopClosure* cl) { diff --git a/src/hotspot/share/jfr/jfr.cpp b/src/hotspot/share/jfr/jfr.cpp index 406f811491f..c7388267996 100644 --- a/src/hotspot/share/jfr/jfr.cpp +++ b/src/hotspot/share/jfr/jfr.cpp @@ -90,12 +90,6 @@ bool Jfr::is_excluded(Thread* t) { return t != NULL && t->jfr_thread_local()->is_excluded(); } -void Jfr::on_java_thread_dismantle(JavaThread* jt) { - if (JfrRecorder::is_recording()) { - JfrCheckpointManager::write_thread_checkpoint(jt); - } -} - void Jfr::on_vm_shutdown(bool exception_handler) { if (JfrRecorder::is_recording()) { JfrEmergencyDump::on_vm_shutdown(exception_handler); diff --git a/src/hotspot/share/jfr/jfr.hpp b/src/hotspot/share/jfr/jfr.hpp index 6b1317832dd..0e9e9035de7 100644 --- a/src/hotspot/share/jfr/jfr.hpp +++ b/src/hotspot/share/jfr/jfr.hpp @@ -49,7 +49,6 @@ class Jfr : AllStatic { static void on_unloading_classes(); static void on_thread_start(Thread* thread); static void on_thread_exit(Thread* thread); - static void on_java_thread_dismantle(JavaThread* jt); static void on_vm_shutdown(bool exception_handler = false); static bool on_flight_recorder_option(const JavaVMOption** option, char* delimiter); static bool on_start_flight_recording_option(const JavaVMOption** option, char* delimiter); diff --git a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp index f29394b88f5..d8d72a916da 100644 --- a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp +++ b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp @@ -54,6 +54,7 @@ #include "runtime/arguments.hpp" #include "runtime/flags/jvmFlag.hpp" #include "runtime/globals.hpp" +#include "runtime/interfaceSupport.inline.hpp" #include "runtime/os.hpp" #include "runtime/os_perf.hpp" #include "runtime/thread.inline.hpp" @@ -174,7 +175,13 @@ TRACE_REQUEST_FUNC(CPULoad) { double u = 0; // user time double s = 0; // kernel time double t = 0; // total time - int ret_val = JfrOSInterface::cpu_loads_process(&u, &s, &t); + int ret_val = OS_ERR; + { + // Can take some time on certain platforms, especially under heavy load. + // Transition to native to avoid unnecessary stalls for pending safepoint synchronizations. + ThreadToNativeFromVM transition((JavaThread*)Thread::current()); + ret_val = JfrOSInterface::cpu_loads_process(&u, &s, &t); + } if (ret_val == OS_ERR) { log_debug(jfr, system)( "Unable to generate requestable event CPULoad"); return; @@ -248,7 +255,13 @@ TRACE_REQUEST_FUNC(SystemProcess) { TRACE_REQUEST_FUNC(ThreadContextSwitchRate) { double rate = 0.0; - int ret_val = JfrOSInterface::context_switch_rate(&rate); + int ret_val = OS_ERR; + { + // Can take some time on certain platforms, especially under heavy load. + // Transition to native to avoid unnecessary stalls for pending safepoint synchronizations. + ThreadToNativeFromVM transition((JavaThread*)Thread::current()); + ret_val = JfrOSInterface::context_switch_rate(&rate); + } if (ret_val == OS_ERR) { log_debug(jfr, system)( "Unable to generate requestable event ThreadContextSwitchRate"); return; diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp index 15ebec72b0b..047ac8f5f7a 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrType.cpp @@ -108,7 +108,7 @@ void JfrCheckpointThreadClosure::do_thread(Thread* t) { void JfrThreadConstantSet::serialize(JfrCheckpointWriter& writer) { JfrCheckpointThreadClosure tc(writer); - JfrJavaThreadIterator javathreads; + JfrJavaThreadIterator javathreads(false); // include not yet live threads (_thread_new) while (javathreads.has_next()) { tc.do_thread(javathreads.next()); } diff --git a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp index 05907a6a757..6a899563641 100644 --- a/src/hotspot/share/jfr/recorder/jfrRecorder.cpp +++ b/src/hotspot/share/jfr/recorder/jfrRecorder.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/javaClasses.hpp" #include "jfr/dcmd/jfrDcmds.hpp" #include "jfr/instrumentation/jfrJvmtiAgent.hpp" #include "jfr/jni/jfrJavaSupport.hpp" diff --git a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp index 50831cb6c76..6d56e01ef11 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrOptionSet.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/javaClasses.hpp" #include "jfr/dcmd/jfrDcmds.hpp" #include "jfr/recorder/service/jfrMemorySizer.hpp" #include "jfr/recorder/service/jfrOptionSet.hpp" diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp index ef72f55fc7c..5d1f0eeeff2 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp @@ -400,8 +400,8 @@ static RecorderState recorder_state = STOPPED; static void set_recorder_state(RecorderState from, RecorderState to) { assert(from == recorder_state, "invariant"); - OrderAccess::storestore(); recorder_state = to; + OrderAccess::fence(); } static void start_recorder() { @@ -417,18 +417,16 @@ static void stop_recorder() { } bool JfrRecorderService::is_recording() { - const bool is_running = recorder_state == RUNNING; - OrderAccess::loadload(); - return is_running; + return recorder_state == RUNNING; } void JfrRecorderService::start() { JfrRotationLock lock; assert(!is_recording(), "invariant"); clear(); - open_new_chunk(); start_recorder(); assert(is_recording(), "invariant"); + open_new_chunk(); } static void stop() { diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp index 65ca9917df3..60077418bba 100644 --- a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp +++ b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp @@ -92,8 +92,8 @@ void JfrThreadLocal::on_start(Thread* t) { assert(Thread::current() == t, "invariant"); JfrJavaSupport::on_thread_start(t); if (JfrRecorder::is_recording()) { + JfrCheckpointManager::write_thread_checkpoint(t); if (!t->jfr_thread_local()->is_excluded()) { - JfrCheckpointManager::write_thread_checkpoint(t); if (t->is_Java_thread()) { send_java_thread_start_event((JavaThread*)t); } diff --git a/src/hotspot/share/jfr/utilities/jfrThreadIterator.cpp b/src/hotspot/share/jfr/utilities/jfrThreadIterator.cpp index e8e753f997f..433c2589380 100644 --- a/src/hotspot/share/jfr/utilities/jfrThreadIterator.cpp +++ b/src/hotspot/share/jfr/utilities/jfrThreadIterator.cpp @@ -32,14 +32,17 @@ static bool thread_inclusion_predicate(Thread* t) { return !t->jfr_thread_local()->is_dead(); } -static bool java_thread_inclusion_predicate(JavaThread* jt) { +static bool java_thread_inclusion_predicate(JavaThread* jt, bool live_only) { assert(jt != NULL, "invariant"); - return thread_inclusion_predicate(jt) && jt->thread_state() != _thread_new; + if (live_only && jt->thread_state() == _thread_new) { + return false; + } + return thread_inclusion_predicate(jt); } -static JavaThread* next_java_thread(JavaThreadIteratorWithHandle& iter) { +static JavaThread* next_java_thread(JavaThreadIteratorWithHandle& iter, bool live_only) { JavaThread* next = iter.next(); - while (next != NULL && !java_thread_inclusion_predicate(next)) { + while (next != NULL && !java_thread_inclusion_predicate(next, live_only)) { next = iter.next(); } return next; @@ -57,17 +60,19 @@ static NonJavaThread* next_non_java_thread(NonJavaThread::Iterator& iter) { return NULL; } -JfrJavaThreadIteratorAdapter::JfrJavaThreadIteratorAdapter() : _iter(), _next(next_java_thread(_iter)) {} +JfrJavaThreadIteratorAdapter::JfrJavaThreadIteratorAdapter(bool live_only /* true */) : _iter(), + _next(next_java_thread(_iter, live_only)), + _live_only(live_only) {} JavaThread* JfrJavaThreadIteratorAdapter::next() { assert(has_next(), "invariant"); Type* const temp = _next; - _next = next_java_thread(_iter); + _next = next_java_thread(_iter, _live_only); assert(temp != _next, "invariant"); return temp; } -JfrNonJavaThreadIteratorAdapter::JfrNonJavaThreadIteratorAdapter() : _iter(), _next(next_non_java_thread(_iter)) {} +JfrNonJavaThreadIteratorAdapter::JfrNonJavaThreadIteratorAdapter(bool live_only /* true */) : _iter(), _next(next_non_java_thread(_iter)) {} bool JfrNonJavaThreadIteratorAdapter::has_next() const { return _next != NULL; diff --git a/src/hotspot/share/jfr/utilities/jfrThreadIterator.hpp b/src/hotspot/share/jfr/utilities/jfrThreadIterator.hpp index c958f4c4fcb..59fa255d759 100644 --- a/src/hotspot/share/jfr/utilities/jfrThreadIterator.hpp +++ b/src/hotspot/share/jfr/utilities/jfrThreadIterator.hpp @@ -34,7 +34,7 @@ class JfrThreadIterator : public AP { private: Adapter _adapter; public: - JfrThreadIterator() : _adapter() {} + JfrThreadIterator(bool live_only = true) : _adapter(live_only) {} typename Adapter::Type* next() { assert(has_next(), "invariant"); return _adapter.next(); @@ -48,9 +48,10 @@ class JfrJavaThreadIteratorAdapter { private: JavaThreadIteratorWithHandle _iter; JavaThread* _next; + bool _live_only; public: typedef JavaThread Type; - JfrJavaThreadIteratorAdapter(); + JfrJavaThreadIteratorAdapter(bool live_only = true); bool has_next() const { return _next != NULL; } @@ -63,7 +64,7 @@ class JfrNonJavaThreadIteratorAdapter { NonJavaThread* _next; public: typedef NonJavaThread Type; - JfrNonJavaThreadIteratorAdapter(); + JfrNonJavaThreadIteratorAdapter(bool live_only = true); bool has_next() const; Type* next(); }; diff --git a/src/hotspot/share/jvmci/jniAccessMark.inline.hpp b/src/hotspot/share/jvmci/jniAccessMark.inline.hpp index e45c5d167d3..9e691313c99 100644 --- a/src/hotspot/share/jvmci/jniAccessMark.inline.hpp +++ b/src/hotspot/share/jvmci/jniAccessMark.inline.hpp @@ -35,12 +35,12 @@ // to a GC in the shared library). class JNIAccessMark : public StackObj { private: - ThreadToNativeFromVM ttnfv; - HandleMark hm; + ThreadToNativeFromVM _ttnfv; + HandleMark _hm; JNIEnv* _env; public: - inline JNIAccessMark(JVMCIEnv* jvmci_env) : - ttnfv(JavaThread::current()), hm(JavaThread::current()) { + inline JNIAccessMark(JVMCIEnv* jvmci_env, JavaThread* thread=JavaThread::current()) : + _ttnfv(thread), _hm(thread) { _env = jvmci_env->_env; } JNIEnv* env() const { return _env; } diff --git a/src/hotspot/share/jvmci/jvmci.cpp b/src/hotspot/share/jvmci/jvmci.cpp index 6129836f494..6607968d123 100644 --- a/src/hotspot/share/jvmci/jvmci.cpp +++ b/src/hotspot/share/jvmci/jvmci.cpp @@ -24,17 +24,21 @@ #include "precompiled.hpp" #include "classfile/systemDictionary.hpp" #include "gc/shared/collectedHeap.hpp" -#include "gc/shared/oopStorage.hpp" -#include "gc/shared/oopStorageSet.hpp" #include "jvmci/jvmci.hpp" #include "jvmci/jvmciJavaClasses.hpp" #include "jvmci/jvmciRuntime.hpp" -#include "jvmci/metadataHandleBlock.hpp" +#include "jvmci/metadataHandles.hpp" +#include "memory/resourceArea.hpp" #include "memory/universe.hpp" -MetadataHandleBlock* JVMCI::_metadata_handles = NULL; JVMCIRuntime* JVMCI::_compiler_runtime = NULL; JVMCIRuntime* JVMCI::_java_runtime = NULL; +volatile bool JVMCI::_is_initialized = false; +void* JVMCI::_shared_library_handle = NULL; +char* JVMCI::_shared_library_path = NULL; +volatile bool JVMCI::_in_shutdown = false; +StringEventLog* JVMCI::_events = NULL; +StringEventLog* JVMCI::_verbose_events = NULL; void jvmci_vmStructs_init() NOT_DEBUG_RETURN; @@ -50,6 +54,40 @@ bool JVMCI::can_initialize_JVMCI() { return true; } +void* JVMCI::get_shared_library(char*& path, bool load) { + void* sl_handle = _shared_library_handle; + if (sl_handle != NULL || !load) { + path = _shared_library_path; + return sl_handle; + } + assert(JVMCI_lock->owner() == Thread::current(), "must be"); + path = NULL; + if (_shared_library_handle == NULL) { + char path[JVM_MAXPATHLEN]; + char ebuf[1024]; + if (JVMCILibPath != NULL) { + if (!os::dll_locate_lib(path, sizeof(path), JVMCILibPath, JVMCI_SHARED_LIBRARY_NAME)) { + vm_exit_during_initialization("Unable to locate JVMCI shared library in path specified by -XX:JVMCILibPath value", JVMCILibPath); + } + } else { + if (!os::dll_locate_lib(path, sizeof(path), Arguments::get_dll_dir(), JVMCI_SHARED_LIBRARY_NAME)) { + vm_exit_during_initialization("Unable to create path to JVMCI shared library"); + } + } + + void* handle = os::dll_load(path, ebuf, sizeof ebuf); + if (handle == NULL) { + vm_exit_during_initialization("Unable to load JVMCI shared library", ebuf); + } + _shared_library_handle = handle; + _shared_library_path = strdup(path); + + JVMCI_event_1("loaded JVMCI shared library from %s", path); + } + path = _shared_library_path; + return _shared_library_handle; +} + void JVMCI::initialize_compiler(TRAPS) { if (JVMCILibDumpJNIConfig) { JNIJVMCI::initialize_ids(NULL); @@ -61,93 +99,105 @@ void JVMCI::initialize_compiler(TRAPS) { void JVMCI::initialize_globals() { jvmci_vmStructs_init(); - _metadata_handles = MetadataHandleBlock::allocate_block(); + if (LogEvents) { + if (JVMCIEventLogLevel > 0) { + _events = new StringEventLog("JVMCI Events", "jvmci"); + if (JVMCIEventLogLevel > 1) { + int count = LogEventsBufferEntries; + for (int i = 1; i < JVMCIEventLogLevel && i < max_EventLog_level; i++) { + // Expand event buffer by 10x for each level above 1 + count = count * 10; + } + _verbose_events = new StringEventLog("Verbose JVMCI Events", "verbose-jvmci", count); + } + } + } if (UseJVMCINativeLibrary) { // There are two runtimes. - _compiler_runtime = new JVMCIRuntime(); - _java_runtime = new JVMCIRuntime(); + _compiler_runtime = new JVMCIRuntime(0); + _java_runtime = new JVMCIRuntime(-1); } else { // There is only a single runtime - _java_runtime = _compiler_runtime = new JVMCIRuntime(); + _java_runtime = _compiler_runtime = new JVMCIRuntime(0); } } -// Handles to objects in the Hotspot heap. -static OopStorage* object_handles() { - return OopStorageSet::vm_global(); -} -jobject JVMCI::make_global(const Handle& obj) { - assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC"); - assert(oopDesc::is_oop(obj()), "not an oop"); - oop* ptr = object_handles()->allocate(); - jobject res = NULL; - if (ptr != NULL) { - assert(*ptr == NULL, "invariant"); - NativeAccess<>::oop_store(ptr, obj()); - res = reinterpret_cast(ptr); - } else { - vm_exit_out_of_memory(sizeof(oop), OOM_MALLOC_ERROR, - "Cannot create JVMCI oop handle"); +void JVMCI::metadata_do(void f(Metadata*)) { + if (_java_runtime != NULL) { + _java_runtime->_metadata_handles->metadata_do(f); + } + if (_compiler_runtime != NULL && _compiler_runtime != _java_runtime) { + _compiler_runtime->_metadata_handles->metadata_do(f); } - return res; -} - -void JVMCI::destroy_global(jobject handle) { - // Assert before nulling out, for better debugging. - assert(is_global_handle(handle), "precondition"); - oop* oop_ptr = reinterpret_cast(handle); - NativeAccess<>::oop_store(oop_ptr, (oop)NULL); - object_handles()->release(oop_ptr); } -bool JVMCI::is_global_handle(jobject handle) { - const oop* ptr = reinterpret_cast(handle); - return object_handles()->allocation_status(ptr) == OopStorage::ALLOCATED_ENTRY; +void JVMCI::do_unloading(bool unloading_occurred) { + if (unloading_occurred) { + if (_java_runtime != NULL) { + _java_runtime->_metadata_handles->do_unloading(); + } + if (_compiler_runtime != NULL && _compiler_runtime != _java_runtime) { + _compiler_runtime->_metadata_handles->do_unloading(); + } + } } -jmetadata JVMCI::allocate_handle(const methodHandle& handle) { - assert(_metadata_handles != NULL, "uninitialized"); - MutexLocker ml(JVMCI_lock); - return _metadata_handles->allocate_handle(handle); +bool JVMCI::is_compiler_initialized() { + return _is_initialized; } -jmetadata JVMCI::allocate_handle(const constantPoolHandle& handle) { - assert(_metadata_handles != NULL, "uninitialized"); - MutexLocker ml(JVMCI_lock); - return _metadata_handles->allocate_handle(handle); +void JVMCI::shutdown() { + ResourceMark rm; + { + MutexLocker locker(JVMCI_lock); + _in_shutdown = true; + JVMCI_event_1("shutting down JVMCI"); + } + JVMCIRuntime* java_runtime = _java_runtime; + if (java_runtime != compiler_runtime()) { + java_runtime->shutdown(); + } + if (compiler_runtime() != NULL) { + compiler_runtime()->shutdown(); + } } -void JVMCI::release_handle(jmetadata handle) { - MutexLocker ml(JVMCI_lock); - _metadata_handles->chain_free_list(handle); +bool JVMCI::in_shutdown() { + return _in_shutdown; } -void JVMCI::metadata_do(void f(Metadata*)) { - if (_metadata_handles != NULL) { - _metadata_handles->metadata_do(f); +void JVMCI::vlog(int level, const char* format, va_list ap) { + if (LogEvents && JVMCIEventLogLevel >= level) { + StringEventLog* events = level == 1 ? _events : _verbose_events; + guarantee(events != NULL, "JVMCI event log not yet initialized"); + Thread* thread = Thread::current_or_null_safe(); + events->logv(thread, format, ap); } } -void JVMCI::do_unloading(bool unloading_occurred) { - if (_metadata_handles != NULL && unloading_occurred) { - _metadata_handles->do_unloading(); +void JVMCI::vtrace(int level, const char* format, va_list ap) { + if (JVMCITraceLevel >= level) { + Thread* thread = Thread::current_or_null_safe(); + if (thread != NULL) { + ResourceMark rm; + tty->print("JVMCITrace-%d[%s]:%*c", level, thread->name(), level, ' '); + } else { + tty->print("JVMCITrace-%d[?]:%*c", level, level, ' '); + } + tty->vprint_cr(format, ap); } } -bool JVMCI::is_compiler_initialized() { - return compiler_runtime()->is_HotSpotJVMCIRuntime_initialized(); +#define LOG_TRACE(level) { va_list ap; \ + va_start(ap, format); vlog(level, format, ap); va_end(ap); \ + va_start(ap, format); vtrace(level, format, ap); va_end(ap); \ } -void JVMCI::shutdown() { - if (compiler_runtime() != NULL) { - compiler_runtime()->shutdown(); - } -} +void JVMCI::event(int level, const char* format, ...) LOG_TRACE(level) +void JVMCI::event1(const char* format, ...) LOG_TRACE(1) +void JVMCI::event2(const char* format, ...) LOG_TRACE(2) +void JVMCI::event3(const char* format, ...) LOG_TRACE(3) +void JVMCI::event4(const char* format, ...) LOG_TRACE(4) -bool JVMCI::shutdown_called() { - if (compiler_runtime() != NULL) { - return compiler_runtime()->shutdown_called(); - } - return false; -} +#undef LOG_TRACE diff --git a/src/hotspot/share/jvmci/jvmci.hpp b/src/hotspot/share/jvmci/jvmci.hpp index 59ae61c0013..f5df7f13532 100644 --- a/src/hotspot/share/jvmci/jvmci.hpp +++ b/src/hotspot/share/jvmci/jvmci.hpp @@ -25,6 +25,7 @@ #define SHARE_JVMCI_JVMCI_HPP #include "compiler/compilerDefinitions.hpp" +#include "utilities/events.hpp" #include "utilities/exceptions.hpp" class BoolObjectClosure; @@ -45,17 +46,36 @@ class JVMCI : public AllStatic { friend class JVMCIEnv; private: - // Handles to Metadata objects. - static MetadataHandleBlock* _metadata_handles; - // Access to the HotSpotJVMCIRuntime used by the CompileBroker. static JVMCIRuntime* _compiler_runtime; - // Access to the HotSpotJVMCIRuntime used by Java code running on the - // HotSpot heap. It will be the same as _compiler_runtime if - // UseJVMCINativeLibrary is false + // True when at least one JVMCIRuntime::initialize_HotSpotJVMCIRuntime() + // execution has completed successfully. + static volatile bool _is_initialized; + + // Handle created when loading the JVMCI shared library with os::dll_load. + // Must hold JVMCI_lock when initializing. + static void* _shared_library_handle; + + // Argument to os::dll_load when loading JVMCI shared library + static char* _shared_library_path; + + // Records whether JVMCI::shutdown has been called. + static volatile bool _in_shutdown; + + // Access to the HotSpot heap based JVMCIRuntime static JVMCIRuntime* _java_runtime; + // JVMCI event log (shows up in hs_err crash logs). + static StringEventLog* _events; + static StringEventLog* _verbose_events; + enum { + max_EventLog_level = 4 + }; + + // Gets the Thread* value for the current thread or NULL if it's not available. + static Thread* current_thread_or_null(); + public: enum CodeInstallResult { ok, @@ -64,13 +84,20 @@ class JVMCI : public AllStatic { code_too_large }; + // Gets the handle to the loaded JVMCI shared library, loading it + // first if not yet loaded and `load` is true. The path from + // which the library is loaded is returned in `path`. If + // `load` is true then JVMCI_lock must be locked. + static void* get_shared_library(char*& path, bool load); + static void do_unloading(bool unloading_occurred); static void metadata_do(void f(Metadata*)); static void shutdown(); - static bool shutdown_called(); + // Returns whether JVMCI::shutdown has been called. + static bool in_shutdown(); static bool is_compiler_initialized(); @@ -83,17 +110,30 @@ class JVMCI : public AllStatic { static void initialize_compiler(TRAPS); - static jobject make_global(const Handle& obj); - static void destroy_global(jobject handle); - static bool is_global_handle(jobject handle); + static JVMCIRuntime* compiler_runtime() { return _compiler_runtime; } + // Gets the single runtime for JVMCI on the Java heap. This is the only + // JVMCI runtime available when !UseJVMCINativeLibrary. + static JVMCIRuntime* java_runtime() { return _java_runtime; } - static jmetadata allocate_handle(const methodHandle& handle); - static jmetadata allocate_handle(const constantPoolHandle& handle); + // Appends an event to the JVMCI event log if JVMCIEventLogLevel >= `level` + static void vlog(int level, const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0); - static void release_handle(jmetadata handle); + // Traces an event to tty if JVMCITraceLevel >= `level` + static void vtrace(int level, const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0); - static JVMCIRuntime* compiler_runtime() { return _compiler_runtime; } - static JVMCIRuntime* java_runtime() { return _java_runtime; } + public: + // Log/trace a JVMCI event + static void event(int level, const char* format, ...) ATTRIBUTE_PRINTF(2, 3); + static void event1(const char* format, ...) ATTRIBUTE_PRINTF(1, 2); + static void event2(const char* format, ...) ATTRIBUTE_PRINTF(1, 2); + static void event3(const char* format, ...) ATTRIBUTE_PRINTF(1, 2); + static void event4(const char* format, ...) ATTRIBUTE_PRINTF(1, 2); }; +// JVMCI event macros. +#define JVMCI_event_1 if (JVMCITraceLevel < 1 && JVMCIEventLogLevel < 1) ; else ::JVMCI::event1 +#define JVMCI_event_2 if (JVMCITraceLevel < 2 && JVMCIEventLogLevel < 2) ; else ::JVMCI::event2 +#define JVMCI_event_3 if (JVMCITraceLevel < 3 && JVMCIEventLogLevel < 3) ; else ::JVMCI::event3 +#define JVMCI_event_4 if (JVMCITraceLevel < 4 && JVMCIEventLogLevel < 4) ; else ::JVMCI::event4 + #endif // SHARE_JVMCI_JVMCI_HPP diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index b31597b008a..a9fe041b6f3 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp @@ -245,14 +245,14 @@ void* CodeInstaller::record_metadata_reference(CodeSection* section, address des assert(!jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant), "unexpected compressed klass pointer %s @ " INTPTR_FORMAT, klass->name()->as_C_string(), p2i(klass)); int index = _oop_recorder->find_index(klass); section->relocate(dest, metadata_Relocation::spec(index)); - TRACE_jvmci_3("metadata[%d of %d] = %s", index, _oop_recorder->metadata_count(), klass->name()->as_C_string()); + JVMCI_event_3("metadata[%d of %d] = %s", index, _oop_recorder->metadata_count(), klass->name()->as_C_string()); return klass; } else if (jvmci_env()->isa_HotSpotResolvedJavaMethodImpl(obj)) { Method* method = jvmci_env()->asMethod(obj); assert(!jvmci_env()->get_HotSpotMetaspaceConstantImpl_compressed(constant), "unexpected compressed method pointer %s @ " INTPTR_FORMAT, method->name()->as_C_string(), p2i(method)); int index = _oop_recorder->find_index(method); section->relocate(dest, metadata_Relocation::spec(index)); - TRACE_jvmci_3("metadata[%d of %d] = %s", index, _oop_recorder->metadata_count(), method->name()->as_C_string()); + JVMCI_event_3("metadata[%d of %d] = %s", index, _oop_recorder->metadata_count(), method->name()->as_C_string()); return method; } else { JVMCI_ERROR_NULL("unexpected metadata reference for constant of type %s", jvmci_env()->klass_name(obj)); @@ -271,7 +271,7 @@ narrowKlass CodeInstaller::record_narrow_metadata_reference(CodeSection* section Klass* klass = JVMCIENV->asKlass(obj); int index = _oop_recorder->find_index(klass); section->relocate(dest, metadata_Relocation::spec(index)); - TRACE_jvmci_3("narrowKlass[%d of %d] = %s", index, _oop_recorder->metadata_count(), klass->name()->as_C_string()); + JVMCI_event_3("narrowKlass[%d of %d] = %s", index, _oop_recorder->metadata_count(), klass->name()->as_C_string()); return CompressedKlassPointers::encode(klass); } #endif @@ -690,7 +690,7 @@ void CodeInstaller::initialize_fields(JVMCIObject target, JVMCIObject compiled_c Thread* thread = Thread::current(); methodHandle method(thread, jvmci_env()->asMethod(hotspotJavaMethod)); _parameter_count = method->size_of_parameters(); - TRACE_jvmci_2("installing code for %s", method->name_and_sig_as_C_string()); + JVMCI_event_2("installing code for %s", method->name_and_sig_as_C_string()); } else { // Must be a HotSpotCompiledRuntimeStub. // Only used in OopMap constructor for non-product builds @@ -883,7 +883,7 @@ JVMCI::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, bo jint pc_offset = jvmci_env()->get_site_Site_pcOffset(site); if (jvmci_env()->isa_site_Call(site)) { - TRACE_jvmci_4("call at %i", pc_offset); + JVMCI_event_4("call at %i", pc_offset); site_Call(buffer, pc_offset, site, JVMCI_CHECK_OK); } else if (jvmci_env()->isa_site_Infopoint(site)) { // three reasons for infopoints denote actual safepoints @@ -891,27 +891,27 @@ JVMCI::CodeInstallResult CodeInstaller::initialize_buffer(CodeBuffer& buffer, bo if (JVMCIENV->equals(reason, jvmci_env()->get_site_InfopointReason_SAFEPOINT()) || JVMCIENV->equals(reason, jvmci_env()->get_site_InfopointReason_CALL()) || JVMCIENV->equals(reason, jvmci_env()->get_site_InfopointReason_IMPLICIT_EXCEPTION())) { - TRACE_jvmci_4("safepoint at %i", pc_offset); + JVMCI_event_4("safepoint at %i", pc_offset); site_Safepoint(buffer, pc_offset, site, JVMCI_CHECK_OK); if (_orig_pc_offset < 0) { JVMCI_ERROR_OK("method contains safepoint, but has no deopt rescue slot"); } if (JVMCIENV->equals(reason, jvmci_env()->get_site_InfopointReason_IMPLICIT_EXCEPTION())) { - TRACE_jvmci_4("implicit exception at %i", pc_offset); + JVMCI_event_4("implicit exception at %i", pc_offset); _implicit_exception_table.add_deoptimize(pc_offset); } } else { - TRACE_jvmci_4("infopoint at %i", pc_offset); + JVMCI_event_4("infopoint at %i", pc_offset); site_Infopoint(buffer, pc_offset, site, JVMCI_CHECK_OK); } } else if (jvmci_env()->isa_site_DataPatch(site)) { - TRACE_jvmci_4("datapatch at %i", pc_offset); + JVMCI_event_4("datapatch at %i", pc_offset); site_DataPatch(buffer, pc_offset, site, JVMCI_CHECK_OK); } else if (jvmci_env()->isa_site_Mark(site)) { - TRACE_jvmci_4("mark at %i", pc_offset); + JVMCI_event_4("mark at %i", pc_offset); site_Mark(buffer, pc_offset, site, JVMCI_CHECK_OK); } else if (jvmci_env()->isa_site_ExceptionHandler(site)) { - TRACE_jvmci_4("exceptionhandler at %i", pc_offset); + JVMCI_event_4("exceptionhandler at %i", pc_offset); site_ExceptionHandler(pc_offset, site); } else { JVMCI_ERROR_OK("unexpected site subclass: %s", jvmci_env()->klass_name(site)); @@ -1100,7 +1100,7 @@ void CodeInstaller::record_scope(jint pc_offset, JVMCIObject position, ScopeMode bci = SynchronizationEntryBCI; } - TRACE_jvmci_2("Recording scope pc_offset=%d bci=%d method=%s", pc_offset, bci, method->name_and_sig_as_C_string()); + JVMCI_event_2("Recording scope pc_offset=%d bci=%d method=%s", pc_offset, bci, method->name_and_sig_as_C_string()); bool reexecute = false; if (frame.is_non_null()) { @@ -1141,8 +1141,8 @@ void CodeInstaller::record_scope(jint pc_offset, JVMCIObject position, ScopeMode GrowableArray* expressions = expression_count > 0 ? new GrowableArray (expression_count) : NULL; GrowableArray* monitors = monitor_count > 0 ? new GrowableArray (monitor_count) : NULL; - TRACE_jvmci_2("Scope at bci %d with %d values", bci, JVMCIENV->get_length(values)); - TRACE_jvmci_2("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count); + JVMCI_event_2("Scope at bci %d with %d values", bci, JVMCIENV->get_length(values)); + JVMCI_event_2("%d locals %d expressions, %d monitors", local_count, expression_count, monitor_count); for (jint i = 0; i < JVMCIENV->get_length(values); i++) { // HandleMark hm(THREAD); @@ -1253,7 +1253,7 @@ void CodeInstaller::site_Call(CodeBuffer& buffer, jint pc_offset, JVMCIObject si JVMCI_ERROR("debug info expected at call at %i", pc_offset); } - TRACE_jvmci_3("method call"); + JVMCI_event_3("method call"); CodeInstaller::pd_relocate_JavaMethod(buffer, hotspot_method, pc_offset, JVMCI_CHECK); if (_next_call_type == INVOKESTATIC || _next_call_type == INVOKESPECIAL) { // Need a static call stub for transitions from compiled to interpreted. diff --git a/src/hotspot/share/jvmci/jvmciCompiler.cpp b/src/hotspot/share/jvmci/jvmciCompiler.cpp index 0e68cb55633..712f2c5ba3a 100644 --- a/src/hotspot/share/jvmci/jvmciCompiler.cpp +++ b/src/hotspot/share/jvmci/jvmciCompiler.cpp @@ -102,43 +102,43 @@ void JVMCICompiler::bootstrap(TRAPS) { (jlong)nanos_to_millis(os::javaTimeNanos() - start), _methods_compiled); } _bootstrapping = false; - JVMCI::compiler_runtime()->bootstrap_finished(CHECK); + JVMCI::java_runtime()->bootstrap_finished(CHECK); } bool JVMCICompiler::force_comp_at_level_simple(const methodHandle& method) { - if (UseJVMCINativeLibrary) { - // This mechanism exists to force compilation of a JVMCI compiler by C1 - // to reduces the compilation time spent on the JVMCI compiler itself. In - // +UseJVMCINativeLibrary mode, the JVMCI compiler is AOT compiled. - return false; - } - if (_bootstrapping) { // When bootstrapping, the JVMCI compiler can compile its own methods. return false; } - - JVMCIRuntime* runtime = JVMCI::compiler_runtime(); - if (runtime != NULL && runtime->is_HotSpotJVMCIRuntime_initialized()) { - JavaThread* thread = JavaThread::current(); - HandleMark hm(thread); - THREAD_JVMCIENV(thread); - JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(JVMCIENV); - objArrayHandle excludeModules(thread, HotSpotJVMCI::HotSpotJVMCIRuntime::excludeFromJVMCICompilation(JVMCIENV, HotSpotJVMCI::resolve(receiver))); - if (excludeModules.not_null()) { - ModuleEntry* moduleEntry = method->method_holder()->module(); - for (int i = 0; i < excludeModules->length(); i++) { - if (excludeModules->obj_at(i) == moduleEntry->module()) { - return true; + if (UseJVMCINativeLibrary) { + // This mechanism exists to force compilation of a JVMCI compiler by C1 + // to reduce the compilation time spent on the JVMCI compiler itself. In + // +UseJVMCINativeLibrary mode, the JVMCI compiler is AOT compiled. + return false; + } else { + JVMCIRuntime* runtime = JVMCI::java_runtime(); + if (runtime != NULL) { + JVMCIObject receiver = runtime->probe_HotSpotJVMCIRuntime(); + if (receiver.is_null()) { + return false; + } + JVMCIEnv* ignored_env = NULL; + objArrayHandle excludeModules(JavaThread::current(), HotSpotJVMCI::HotSpotJVMCIRuntime::excludeFromJVMCICompilation(ignored_env, HotSpotJVMCI::resolve(receiver))); + if (excludeModules.not_null()) { + ModuleEntry* moduleEntry = method->method_holder()->module(); + for (int i = 0; i < excludeModules->length(); i++) { + if (excludeModules->obj_at(i) == moduleEntry->module()) { + return true; + } } } } + return false; } - return false; } // Compilation entry point for methods -void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) { +void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, bool install_code, DirectiveSet* directive) { ShouldNotReachHere(); } @@ -149,6 +149,6 @@ void JVMCICompiler::print_timers() { // Print compilation timers and statistics void JVMCICompiler::print_compilation_timers() { - TRACE_jvmci_1("JVMCICompiler::print_timers"); + JVMCI_event_1("JVMCICompiler::print_timers"); tty->print_cr(" JVMCI code install time: %6.3f s", _codeInstallTimer.seconds()); } diff --git a/src/hotspot/share/jvmci/jvmciCompiler.hpp b/src/hotspot/share/jvmci/jvmciCompiler.hpp index e178f6d886a..b522a54f525 100644 --- a/src/hotspot/share/jvmci/jvmciCompiler.hpp +++ b/src/hotspot/share/jvmci/jvmciCompiler.hpp @@ -94,7 +94,7 @@ class JVMCICompiler : public AbstractCompiler { } // Compilation entry point for methods - virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive); + virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, bool install_code, DirectiveSet* directive); // Print compilation timers and statistics virtual void print_timers(); diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 3189df4d9ba..dc1831d3b9e 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -103,14 +103,10 @@ class JVMCITraceMark : public StackObj { public: JVMCITraceMark(const char* msg) { _msg = msg; - if (JVMCITraceLevel >= 1) { - tty->print_cr(PTR_FORMAT " JVMCITrace-1: Enter %s", p2i(JavaThread::current()), _msg); - } + JVMCI_event_2("Enter %s", _msg); } ~JVMCITraceMark() { - if (JVMCITraceLevel >= 1) { - tty->print_cr(PTR_FORMAT " JVMCITrace-1: Exit %s", p2i(JavaThread::current()), _msg); - } + JVMCI_event_2(" Exit %s", _msg); } }; @@ -137,35 +133,37 @@ Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) { ResourceMark rm; \ JNI_JVMCIENV(thread, env); -static Thread* get_current_thread() { - return Thread::current_or_null_safe(); +static JavaThread* get_current_thread(bool allow_null=true) { + Thread* thread = Thread::current_or_null_safe(); + if (thread == NULL) { + assert(allow_null, "npe"); + return NULL; + } + assert(thread->is_Java_thread(), "must be"); + return (JavaThread*) thread; } // Entry to native method implementation that transitions // current thread to '_thread_in_vm'. #define C2V_VMENTRY(result_type, name, signature) \ JNIEXPORT result_type JNICALL c2v_ ## name signature { \ - Thread* base_thread = get_current_thread(); \ - if (base_thread == NULL) { \ + JavaThread* thread = get_current_thread(); \ + if (thread == NULL) { \ env->ThrowNew(JNIJVMCI::InternalError::clazz(), \ err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \ return; \ } \ - assert(base_thread->is_Java_thread(), "just checking");\ - JavaThread* thread = (JavaThread*) base_thread; \ JVMCITraceMark jtm("CompilerToVM::" #name); \ C2V_BLOCK(result_type, name, signature) #define C2V_VMENTRY_(result_type, name, signature, result) \ JNIEXPORT result_type JNICALL c2v_ ## name signature { \ - Thread* base_thread = get_current_thread(); \ - if (base_thread == NULL) { \ + JavaThread* thread = get_current_thread(); \ + if (thread == NULL) { \ env->ThrowNew(JNIJVMCI::InternalError::clazz(), \ err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \ return result; \ } \ - assert(base_thread->is_Java_thread(), "just checking");\ - JavaThread* thread = (JavaThread*) base_thread; \ JVMCITraceMark jtm("CompilerToVM::" #name); \ C2V_BLOCK(result_type, name, signature) @@ -176,7 +174,7 @@ static Thread* get_current_thread() { // current thread to '_thread_in_vm'. #define C2V_VMENTRY_PREFIX(result_type, name, signature) \ JNIEXPORT result_type JNICALL c2v_ ## name signature { \ - Thread* base_thread = get_current_thread(); + JavaThread* thread = get_current_thread(); #define C2V_END } @@ -1579,7 +1577,7 @@ extern "C" void jio_printf(const char *fmt, ...); class AttachDetach : public StackObj { public: bool _attached; - AttachDetach(JNIEnv* env, Thread* current_thread) { + AttachDetach(JNIEnv* env, JavaThread* current_thread) { if (current_thread == NULL) { extern struct JavaVM_ main_vm; JNIEnv* hotspotEnv; @@ -1608,18 +1606,17 @@ class AttachDetach : public StackObj { }; C2V_VMENTRY_PREFIX(jint, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length, bool flush, bool can_throw)) - AttachDetach ad(env, base_thread); + AttachDetach ad(env, thread); bool use_tty = true; - if (base_thread == NULL) { + if (thread == NULL) { if (!ad._attached) { // Can only use tty if the current thread is attached + JVMCI_event_1("Cannot write to tty on unattached thread"); return 0; } - base_thread = get_current_thread(); + thread = get_current_thread(); } JVMCITraceMark jtm("writeDebugOutput"); - assert(base_thread->is_Java_thread(), "just checking"); - JavaThread* thread = (JavaThread*) base_thread; C2V_BLOCK(void, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length)) if (bytes == NULL) { if (can_throw) { @@ -2229,7 +2226,7 @@ C2V_VMENTRY_NULL(jobject, getObject, (JNIEnv* env, jobject, jobject x, long disp C2V_VMENTRY(void, deleteGlobalHandle, (JNIEnv* env, jobject, jlong h)) jobject handle = (jobject)(address)h; if (handle != NULL) { - JVMCI::destroy_global(handle); + JVMCIENV->runtime()->destroy_global(handle); } } @@ -2239,31 +2236,24 @@ static void requireJVMCINativeLibrary(JVMCI_TRAPS) { } } -static JavaVM* requireNativeLibraryJavaVM(const char* caller, JVMCI_TRAPS) { - JavaVM* javaVM = JVMCIEnv::get_shared_library_javavm(); - if (javaVM == NULL) { - JVMCI_THROW_MSG_NULL(IllegalStateException, err_msg("Require JVMCI shared library to be initialized in %s", caller)); - } - return javaVM; -} - C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclass mirror)) requireJVMCINativeLibrary(JVMCI_CHECK_NULL); requireInHotSpot("registerNativeMethods", JVMCI_CHECK_NULL); - void* shared_library = JVMCIEnv::get_shared_library_handle(); - if (shared_library == NULL) { + char* sl_path; + void* sl_handle; + JVMCIRuntime* runtime = JVMCI::compiler_runtime(); + { // Ensure the JVMCI shared library runtime is initialized. JVMCIEnv __peer_jvmci_env__(thread, false, __FILE__, __LINE__); JVMCIEnv* peerEnv = &__peer_jvmci_env__; HandleMark hm; - JVMCIRuntime* runtime = JVMCI::compiler_runtime(); JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(peerEnv); if (peerEnv->has_pending_exception()) { peerEnv->describe_pending_exception(true); } - shared_library = JVMCIEnv::get_shared_library_handle(); - if (shared_library == NULL) { - JVMCI_THROW_MSG_0(InternalError, "Error initializing JVMCI runtime"); + sl_handle = JVMCI::get_shared_library(sl_path, false); + if (sl_handle == NULL) { + JVMCI_THROW_MSG_0(InternalError, err_msg("Error initializing JVMCI runtime %d", runtime->id())); } } @@ -2293,7 +2283,7 @@ C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclas os::print_jni_name_suffix_on(&st, args_size); char* jni_name = st.as_string(); - address entry = (address) os::dll_lookup(shared_library, jni_name); + address entry = (address) os::dll_lookup(sl_handle, jni_name); if (entry == NULL) { // 2) Try JNI long style st.reset(); @@ -2303,11 +2293,11 @@ C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclas st.print_raw(long_name); os::print_jni_name_suffix_on(&st, args_size); char* jni_long_name = st.as_string(); - entry = (address) os::dll_lookup(shared_library, jni_long_name); + entry = (address) os::dll_lookup(sl_handle, jni_long_name); if (entry == NULL) { JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("%s [neither %s nor %s exist in %s]", method->name_and_sig_as_C_string(), - jni_name, jni_long_name, JVMCIEnv::get_shared_library_path())); + jni_name, jni_long_name, sl_path)); } } @@ -2316,81 +2306,83 @@ C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclas method->name_and_sig_as_C_string(), p2i(method->native_function()), p2i(entry))); } method->set_native_function(entry, Method::native_bind_event_is_interesting); - log_debug(jni, resolve)("[Dynamic-linking native method %s.%s ... JNI]", + log_debug(jni, resolve)("[Dynamic-linking native method %s.%s ... JNI] @ " PTR_FORMAT, method->method_holder()->external_name(), - method->name()->as_C_string()); + method->name()->as_C_string(), + p2i((void*) entry)); } } - JavaVM* javaVM = JVMCIEnv::get_shared_library_javavm(); - JVMCIPrimitiveArray result = JVMCIENV->new_longArray(4, JVMCI_CHECK_NULL); - JVMCIENV->put_long_at(result, 0, (jlong) (address) javaVM); - JVMCIENV->put_long_at(result, 1, (jlong) (address) javaVM->functions->reserved0); - JVMCIENV->put_long_at(result, 2, (jlong) (address) javaVM->functions->reserved1); - JVMCIENV->put_long_at(result, 3, (jlong) (address) javaVM->functions->reserved2); - return (jlongArray) JVMCIENV->get_jobject(result); + typeArrayOop info_oop = oopFactory::new_longArray(4, CHECK_0); + jlongArray info = (jlongArray) JNIHandles::make_local(info_oop); + runtime->init_JavaVM_info(info, JVMCI_CHECK_0); + return info; } C2V_VMENTRY_PREFIX(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject c2vm)) - if (base_thread == NULL) { + if (thread == NULL) { // Called from unattached JVMCI shared library thread return false; } JVMCITraceMark jtm("isCurrentThreadAttached"); - assert(base_thread->is_Java_thread(), "just checking"); - JavaThread* thread = (JavaThread*) base_thread; if (thread->jni_environment() == env) { C2V_BLOCK(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject)) requireJVMCINativeLibrary(JVMCI_CHECK_0); - JavaVM* javaVM = requireNativeLibraryJavaVM("isCurrentThreadAttached", JVMCI_CHECK_0); + JVMCIRuntime* runtime = JVMCI::compiler_runtime(); + if (runtime == NULL || !runtime->has_shared_library_javavm()) { + JVMCI_THROW_MSG_0(IllegalStateException, "Require JVMCI shared library JavaVM to be initialized in isCurrentThreadAttached"); + } JNIEnv* peerEnv; - return javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) == JNI_OK; + return runtime->GetEnv(thread, (void**) &peerEnv, JNI_VERSION_1_2) == JNI_OK; } return true; C2V_END C2V_VMENTRY_PREFIX(jlong, getCurrentJavaThread, (JNIEnv* env, jobject c2vm)) - if (base_thread == NULL) { + if (thread == NULL) { // Called from unattached JVMCI shared library thread return 0L; } JVMCITraceMark jtm("getCurrentJavaThread"); - assert(base_thread->is_Java_thread(), "just checking"); - return (jlong) p2i(base_thread); + return (jlong) p2i(thread); C2V_END C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jboolean as_daemon)) - if (base_thread == NULL) { + if (thread == NULL) { // Called from unattached JVMCI shared library thread extern struct JavaVM_ main_vm; JNIEnv* hotspotEnv; - jint res = as_daemon ? main_vm.AttachCurrentThreadAsDaemon((void**)&hotspotEnv, NULL) : - main_vm.AttachCurrentThread((void**)&hotspotEnv, NULL); + jint res = as_daemon ? main_vm.AttachCurrentThreadAsDaemon((void**) &hotspotEnv, NULL) : + main_vm.AttachCurrentThread((void**) &hotspotEnv, NULL); if (res != JNI_OK) { JNI_THROW_("attachCurrentThread", InternalError, err_msg("Trying to attach thread returned %d", res), false); } return true; } JVMCITraceMark jtm("attachCurrentThread"); - assert(base_thread->is_Java_thread(), "just checking");\ - JavaThread* thread = (JavaThread*) base_thread; if (thread->jni_environment() == env) { // Called from HotSpot C2V_BLOCK(jboolean, attachCurrentThread, (JNIEnv* env, jobject, jboolean)) requireJVMCINativeLibrary(JVMCI_CHECK_0); - JavaVM* javaVM = requireNativeLibraryJavaVM("attachCurrentThread", JVMCI_CHECK_0); + JVMCIRuntime* runtime = JVMCI::compiler_runtime(); + if (runtime == NULL || !runtime->has_shared_library_javavm()) { + JVMCI_THROW_MSG_0(IllegalStateException, "Require JVMCI shared library JavaVM to be initialized in attachCurrentThread"); + } + JavaVMAttachArgs attach_args; attach_args.version = JNI_VERSION_1_2; attach_args.name = thread->name(); attach_args.group = NULL; - JNIEnv* peerEnv; - if (javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) == JNI_OK) { + JNIEnv* peerJNIEnv; + if (runtime->GetEnv(thread, (void**) &peerJNIEnv, JNI_VERSION_1_2) == JNI_OK) { return false; } - jint res = as_daemon ? javaVM->AttachCurrentThreadAsDaemon((void**)&peerEnv, &attach_args) : - javaVM->AttachCurrentThread((void**)&peerEnv, &attach_args); + jint res = as_daemon ? runtime->AttachCurrentThreadAsDaemon(thread, (void**) &peerJNIEnv, &attach_args) : + runtime->AttachCurrentThread(thread, (void**) &peerJNIEnv, &attach_args); + if (res == JNI_OK) { - guarantee(peerEnv != NULL, "must be"); + guarantee(peerJNIEnv != NULL, "must be"); + JVMCI_event_1("attached to JavaVM for JVMCI runtime %d", runtime->id()); return true; } JVMCI_THROW_MSG_0(InternalError, err_msg("Error %d while attaching %s", res, attach_args.name)); @@ -2400,24 +2392,25 @@ C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jb C2V_END C2V_VMENTRY_PREFIX(void, detachCurrentThread, (JNIEnv* env, jobject c2vm)) - if (base_thread == NULL) { + if (thread == NULL) { // Called from unattached JVMCI shared library thread - JNI_THROW("detachCurrentThread", IllegalStateException, err_msg("Cannot detach non-attached thread")); + JNI_THROW("detachCurrentThread", IllegalStateException, "Cannot detach non-attached thread"); } JVMCITraceMark jtm("detachCurrentThread"); - assert(base_thread->is_Java_thread(), "just checking");\ - JavaThread* thread = (JavaThread*) base_thread; if (thread->jni_environment() == env) { // Called from HotSpot C2V_BLOCK(void, detachCurrentThread, (JNIEnv* env, jobject)) requireJVMCINativeLibrary(JVMCI_CHECK); requireInHotSpot("detachCurrentThread", JVMCI_CHECK); - JavaVM* javaVM = requireNativeLibraryJavaVM("detachCurrentThread", JVMCI_CHECK); - JNIEnv* peerEnv; - if (javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) != JNI_OK) { + JVMCIRuntime* runtime = JVMCI::compiler_runtime(); + if (runtime == NULL || !runtime->has_shared_library_javavm()) { + JVMCI_THROW_MSG(IllegalStateException, "Require JVMCI shared library JavaVM to be initialized in detachCurrentThread"); + } + JNIEnv* peerJNIEnv; + if (runtime->GetEnv(thread, (void**) &peerJNIEnv, JNI_VERSION_1_2) != JNI_OK) { JVMCI_THROW_MSG(IllegalStateException, err_msg("Cannot detach non-attached thread: %s", thread->name())); } - jint res = javaVM->DetachCurrentThread(); + jint res = runtime->DetachCurrentThread(thread); if (res != JNI_OK) { JVMCI_THROW_MSG(InternalError, err_msg("Error %d while attaching %s", res, thread->name())); } @@ -2426,7 +2419,7 @@ C2V_VMENTRY_PREFIX(void, detachCurrentThread, (JNIEnv* env, jobject c2vm)) extern struct JavaVM_ main_vm; jint res = main_vm.DetachCurrentThread(); if (res != JNI_OK) { - JNI_THROW("detachCurrentThread", InternalError, err_msg("Cannot detach non-attached thread")); + JNI_THROW("detachCurrentThread", InternalError, "Cannot detach non-attached thread"); } } C2V_END diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index 0000deae674..b8deb73913d 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -77,10 +77,6 @@ bool JVMCICompileState::jvmti_state_changed() const { return false; } -JavaVM* JVMCIEnv::_shared_library_javavm = NULL; -void* JVMCIEnv::_shared_library_handle = NULL; -char* JVMCIEnv::_shared_library_path = NULL; - void JVMCIEnv::copy_saved_properties() { assert(!is_hotspot(), "can only copy saved properties from HotSpot to native image"); @@ -131,7 +127,7 @@ void JVMCIEnv::copy_saved_properties() { // Initialize saved properties in shared library jclass servicesClass = JNIJVMCI::Services::clazz(); jmethodID initializeSavedProperties = JNIJVMCI::Services::initializeSavedProperties_method(); - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jni()->CallStaticVoidMethod(servicesClass, initializeSavedProperties, buf.as_jobject()); if (jni()->ExceptionCheck()) { jni()->ExceptionDescribe(); @@ -139,67 +135,14 @@ void JVMCIEnv::copy_saved_properties() { } } -JNIEnv* JVMCIEnv::init_shared_library(JavaThread* thread) { - if (_shared_library_javavm == NULL) { - MutexLocker locker(JVMCI_lock); - if (_shared_library_javavm == NULL) { - char path[JVM_MAXPATHLEN]; - char ebuf[1024]; - if (JVMCILibPath != NULL) { - if (!os::dll_locate_lib(path, sizeof(path), JVMCILibPath, JVMCI_SHARED_LIBRARY_NAME)) { - vm_exit_during_initialization("Unable to create JVMCI shared library path from -XX:JVMCILibPath value", JVMCILibPath); - } - } else { - if (!os::dll_locate_lib(path, sizeof(path), Arguments::get_dll_dir(), JVMCI_SHARED_LIBRARY_NAME)) { - vm_exit_during_initialization("Unable to create path to JVMCI shared library"); - } - } - - void* handle = os::dll_load(path, ebuf, sizeof ebuf); - if (handle == NULL) { - vm_exit_during_initialization("Unable to load JVMCI shared library", ebuf); - } - _shared_library_handle = handle; - _shared_library_path = strdup(path); - jint (*JNI_CreateJavaVM)(JavaVM **pvm, void **penv, void *args); - typedef jint (*JNI_CreateJavaVM_t)(JavaVM **pvm, void **penv, void *args); - - JNI_CreateJavaVM = CAST_TO_FN_PTR(JNI_CreateJavaVM_t, os::dll_lookup(handle, "JNI_CreateJavaVM")); - JNIEnv* env; - if (JNI_CreateJavaVM == NULL) { - vm_exit_during_initialization("Unable to find JNI_CreateJavaVM", path); - } - - ResourceMark rm; - JavaVMInitArgs vm_args; - vm_args.version = JNI_VERSION_1_2; - vm_args.ignoreUnrecognized = JNI_TRUE; - vm_args.options = NULL; - vm_args.nOptions = 0; - - JavaVM* the_javavm = NULL; - int result = (*JNI_CreateJavaVM)(&the_javavm, (void**) &env, &vm_args); - if (result == JNI_OK) { - guarantee(env != NULL, "missing env"); - _shared_library_javavm = the_javavm; - return env; - } else { - vm_exit_during_initialization(err_msg("JNI_CreateJavaVM failed with return value %d", result), path); - } - } - } - return NULL; -} - void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) { assert(thread != NULL, "npe"); - // By default there is only one runtime which is the compiler runtime. - _runtime = JVMCI::compiler_runtime(); _env = NULL; _pop_frame_on_close = false; _detach_on_close = false; if (!UseJVMCINativeLibrary) { // In HotSpot mode, JNI isn't used at all. + _runtime = JVMCI::java_runtime(); _is_hotspot = true; return; } @@ -213,6 +156,8 @@ void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) { _runtime = JVMCI::java_runtime(); return; } + _runtime = JVMCI::compiler_runtime(); + assert(_runtime != NULL, "npe"); _env = parent_env; return; } @@ -220,13 +165,15 @@ void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) { // Running in JVMCI shared library mode so ensure the shared library // is loaded and initialized and get a shared library JNIEnv _is_hotspot = false; - _env = init_shared_library(thread); + + _runtime = JVMCI::compiler_runtime(); + _env = _runtime->init_shared_library_javavm(); if (_env != NULL) { // Creating the JVMCI shared library VM also attaches the current thread _detach_on_close = true; } else { - _shared_library_javavm->GetEnv((void**)&parent_env, JNI_VERSION_1_2); + _runtime->GetEnv(thread, (void**)&parent_env, JNI_VERSION_1_2); if (parent_env != NULL) { // Even though there's a parent JNI env, there's no guarantee // it was opened by a JVMCIEnv scope and thus may not have @@ -240,7 +187,7 @@ void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) { attach_args.version = JNI_VERSION_1_2; attach_args.name = thread->name(); attach_args.group = NULL; - if (_shared_library_javavm->AttachCurrentThread((void**)&_env, &attach_args) != JNI_OK) { + if (_runtime->AttachCurrentThread(thread, (void**) &_env, &attach_args) != JNI_OK) { fatal("Error attaching current thread (%s) to JVMCI shared library JNI interface", attach_args.name); } _detach_on_close = true; @@ -250,7 +197,7 @@ void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) { assert(_env != NULL, "missing env"); assert(_throw_to_caller == false, "must be"); - JNIAccessMark jni(this); + JNIAccessMark jni(this, thread); jint result = _env->PushLocalFrame(32); if (result != JNI_OK) { char message[256]; @@ -294,6 +241,7 @@ void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, const char* file, int l // Prints a pending exception (if any) and its stack trace. void JVMCIEnv::describe_pending_exception(bool clear) { + Thread* THREAD = Thread::current(); if (!is_hotspot()) { JNIAccessMark jni(this); if (jni()->ExceptionCheck()) { @@ -304,7 +252,6 @@ void JVMCIEnv::describe_pending_exception(bool clear) { } } } else { - Thread* THREAD = Thread::current(); if (HAS_PENDING_EXCEPTION) { JVMCIRuntime::describe_pending_hotspot_exception((JavaThread*) THREAD, clear); } @@ -332,7 +279,7 @@ void JVMCIEnv::translate_hotspot_exception_to_jni_exception(JavaThread* THREAD, ResourceMark rm; const char* encoded_throwable_chars = java_lang_String::as_utf8_string(encoded_throwable_string); - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject jni_encoded_throwable_string = jni()->NewStringUTF(encoded_throwable_chars); jthrowable jni_throwable = (jthrowable) jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::decodeThrowable_method(), @@ -368,7 +315,7 @@ JVMCIEnv::~JVMCIEnv() { } if (_detach_on_close) { - get_shared_library_javavm()->DetachCurrentThread(); + _runtime->DetachCurrentThread(JavaThread::current()); } } } @@ -603,12 +550,12 @@ JVMCIObject JVMCIEnv::create_box(BasicType type, jvalue* value, JVMCI_TRAPS) { default: JVMCI_THROW_MSG_(IllegalArgumentException, "Only boxes for primitive values can be created", JVMCIObject()); } + JavaThread* THREAD = JavaThread::current(); if (is_hotspot()) { - JavaThread* THREAD = JavaThread::current(); oop box = java_lang_boxing_object::create(type, value, CHECK_(JVMCIObject())); return HotSpotJVMCI::wrap(box); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject box = jni()->NewObjectA(JNIJVMCI::box_class(type), JNIJVMCI::box_constructor(type), value); assert(box != NULL, ""); return wrap(box); @@ -672,13 +619,13 @@ void JVMCIEnv::fthrow_error(const char* file, int line, const char* format, ...) vsnprintf(msg, max_msg_size, format, ap); msg[max_msg_size-1] = '\0'; va_end(ap); + JavaThread* THREAD = JavaThread::current(); if (is_hotspot()) { - JavaThread* THREAD = JavaThread::current(); Handle h_loader = Handle(); Handle h_protection_domain = Handle(); Exceptions::_throw_msg(THREAD, file, line, vmSymbols::jdk_vm_ci_common_JVMCIError(), msg, h_loader, h_protection_domain); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jni()->ThrowNew(JNIJVMCI::JVMCIError::clazz(), msg); } } @@ -735,7 +682,7 @@ void JVMCIEnv::call_HotSpotJVMCIRuntime_shutdown (JVMCIObject runtime) { JavaValue result(T_VOID); JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::shutdown_name(), vmSymbols::void_method_signature(), &jargs, THREAD); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::shutdown_method()); } if (has_pending_exception()) { @@ -753,7 +700,7 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_runtime (JVMCIEnv* JVMCIENV) { JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::runtime_name(), vmSymbols::runtime_signature(), &jargs, CHECK_(JVMCIObject())); return wrap((oop) result.get_jobject()); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::runtime_method()); if (jni()->ExceptionCheck()) { return JVMCIObject(); @@ -770,7 +717,7 @@ JVMCIObject JVMCIEnv::call_JVMCI_getRuntime (JVMCIEnv* JVMCIENV) { JavaCalls::call_static(&result, HotSpotJVMCI::JVMCI::klass(), vmSymbols::getRuntime_name(), vmSymbols::getRuntime_signature(), &jargs, CHECK_(JVMCIObject())); return wrap((oop) result.get_jobject()); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::JVMCI::clazz(), JNIJVMCI::JVMCI::getRuntime_method()); if (jni()->ExceptionCheck()) { return JVMCIObject(); @@ -788,7 +735,7 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_getCompiler (JVMCIObject runtime, JavaCalls::call_virtual(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::getCompiler_name(), vmSymbols::getCompiler_signature(), &jargs, CHECK_(JVMCIObject())); return wrap((oop) result.get_jobject()); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject result = jni()->CallObjectMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::getCompiler_method()); if (jni()->ExceptionCheck()) { return JVMCIObject(); @@ -810,7 +757,7 @@ JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, vmSymbols::callToString_signature(), &jargs, CHECK_(JVMCIObject())); return wrap((oop) result.get_jobject()); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::callToString_method(), object.as_jobject()); @@ -835,7 +782,7 @@ JVMCIObject JVMCIEnv::call_PrimitiveConstant_forTypeChar(jchar kind, jlong value vmSymbols::forTypeChar_signature(), &jargs, CHECK_(JVMCIObject())); return wrap((oop) result.get_jobject()); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::PrimitiveConstant::clazz(), JNIJVMCI::PrimitiveConstant::forTypeChar_method(), kind, value); @@ -858,7 +805,7 @@ JVMCIObject JVMCIEnv::call_JavaConstant_forFloat(float value, JVMCI_TRAPS) { vmSymbols::forFloat_signature(), &jargs, CHECK_(JVMCIObject())); return wrap((oop) result.get_jobject()); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(), JNIJVMCI::JavaConstant::forFloat_method(), value); @@ -881,7 +828,7 @@ JVMCIObject JVMCIEnv::call_JavaConstant_forDouble(double value, JVMCI_TRAPS) { vmSymbols::forDouble_signature(), &jargs, CHECK_(JVMCIObject())); return wrap((oop) result.get_jobject()); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(), JNIJVMCI::JavaConstant::forDouble_method(), value); @@ -926,7 +873,7 @@ JVMCIObject JVMCIEnv::new_StackTraceElement(const methodHandle& method, int bci, HotSpotJVMCI::StackTraceElement::set_lineNumber(this, obj(), line_number); return wrap(obj()); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject declaring_class = jni()->NewStringUTF(declaring_class_str); if (jni()->ExceptionCheck()) { return JVMCIObject(); @@ -978,7 +925,7 @@ JVMCIObject JVMCIEnv::new_HotSpotNmethod(const methodHandle& method, const char* &jargs, CHECK_(JVMCIObject())); return wrap(obj_h()); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject nameStr = name == NULL ? NULL : jni()->NewStringUTF(name); if (jni()->ExceptionCheck()) { return JVMCIObject(); @@ -1015,18 +962,6 @@ JVMCIObject JVMCIEnv::make_global(JVMCIObject object) { } } -JVMCIObject JVMCIEnv::make_weak(JVMCIObject object) { - if (object.is_null()) { - return JVMCIObject(); - } - if (is_hotspot()) { - return wrap(JNIHandles::make_weak_global(Handle(Thread::current(), HotSpotJVMCI::resolve(object)))); - } else { - JNIAccessMark jni(this); - return wrap(jni()->NewWeakGlobalRef(object.as_jobject())); - } -} - void JVMCIEnv::destroy_local(JVMCIObject object) { if (is_hotspot()) { JNIHandles::destroy_local(object.as_jobject()); @@ -1045,15 +980,6 @@ void JVMCIEnv::destroy_global(JVMCIObject object) { } } -void JVMCIEnv::destroy_weak(JVMCIObject object) { - if (is_hotspot()) { - JNIHandles::destroy_weak_global(object.as_jweak()); - } else { - JNIAccessMark jni(this); - jni()->DeleteWeakGlobalRef(object.as_jweak()); - } -} - const char* JVMCIEnv::klass_name(JVMCIObject object) { if (is_hotspot()) { return HotSpotJVMCI::resolve(object)->klass()->signature_name(); @@ -1076,7 +1002,7 @@ JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS) } Thread* THREAD = Thread::current(); - jmetadata handle = JVMCI::allocate_handle(method); + jmetadata handle = _runtime->allocate_handle(method); jboolean exception = false; if (is_hotspot()) { JavaValue result(T_OBJECT); @@ -1099,13 +1025,13 @@ JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS) } if (exception) { - JVMCI::release_handle(handle); + _runtime->release_handle(handle); return JVMCIObject(); } assert(asMethod(method_object) == method(), "must be"); if (get_HotSpotResolvedJavaMethodImpl_metadataHandle(method_object) != (jlong) handle) { - JVMCI::release_handle(handle); + _runtime->release_handle(handle); } assert(!method_object.is_null(), "must be"); return method_object; @@ -1137,7 +1063,7 @@ JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS) type = wrap((oop)result.get_jobject()); } } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); HandleMark hm(THREAD); type = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedObjectTypeImpl::clazz(), @@ -1155,10 +1081,10 @@ JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS) JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMCI_TRAPS) { JVMCIObject cp_object; - jmetadata handle = JVMCI::allocate_handle(cp); + jmetadata handle = _runtime->allocate_handle(cp); jboolean exception = false; + JavaThread* THREAD = JavaThread::current(); if (is_hotspot()) { - JavaThread* THREAD = JavaThread::current(); JavaValue result(T_OBJECT); JavaCallArguments args; args.push_long((jlong) handle); @@ -1172,7 +1098,7 @@ JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMC cp_object = wrap((oop)result.get_jobject()); } } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); cp_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotConstantPool::clazz(), JNIJVMCI::HotSpotConstantPool_fromMetaspace_method(), (jlong) handle)); @@ -1180,7 +1106,7 @@ JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMC } if (exception) { - JVMCI::release_handle(handle); + _runtime->release_handle(handle); return JVMCIObject(); } @@ -1191,69 +1117,69 @@ JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMC } JVMCIPrimitiveArray JVMCIEnv::new_booleanArray(int length, JVMCI_TRAPS) { + JavaThread* THREAD = JavaThread::current(); if (is_hotspot()) { - JavaThread* THREAD = JavaThread::current(); typeArrayOop result = oopFactory::new_boolArray(length, CHECK_(JVMCIObject())); return wrap(result); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jbooleanArray result = jni()->NewBooleanArray(length); return wrap(result); } } JVMCIPrimitiveArray JVMCIEnv::new_byteArray(int length, JVMCI_TRAPS) { + JavaThread* THREAD = JavaThread::current(); if (is_hotspot()) { - JavaThread* THREAD = JavaThread::current(); typeArrayOop result = oopFactory::new_byteArray(length, CHECK_(JVMCIObject())); return wrap(result); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jbyteArray result = jni()->NewByteArray(length); return wrap(result); } } JVMCIObjectArray JVMCIEnv::new_byte_array_array(int length, JVMCI_TRAPS) { + JavaThread* THREAD = JavaThread::current(); if (is_hotspot()) { - JavaThread* THREAD = JavaThread::current(); Klass* byteArrayArrayKlass = TypeArrayKlass::cast(Universe::byteArrayKlassObj ())->array_klass(CHECK_(JVMCIObject())); objArrayOop result = ObjArrayKlass::cast(byteArrayArrayKlass) ->allocate(length, CHECK_(JVMCIObject())); return wrap(result); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobjectArray result = jni()->NewObjectArray(length, JNIJVMCI::byte_array(), NULL); return wrap(result); } } JVMCIPrimitiveArray JVMCIEnv::new_intArray(int length, JVMCI_TRAPS) { + JavaThread* THREAD = JavaThread::current(); if (is_hotspot()) { - JavaThread* THREAD = JavaThread::current(); typeArrayOop result = oopFactory::new_intArray(length, CHECK_(JVMCIObject())); return wrap(result); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jintArray result = jni()->NewIntArray(length); return wrap(result); } } JVMCIPrimitiveArray JVMCIEnv::new_longArray(int length, JVMCI_TRAPS) { + JavaThread* THREAD = JavaThread::current(); if (is_hotspot()) { - JavaThread* THREAD = JavaThread::current(); typeArrayOop result = oopFactory::new_longArray(length, CHECK_(JVMCIObject())); return wrap(result); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jlongArray result = jni()->NewLongArray(length); return wrap(result); } } JVMCIObject JVMCIEnv::new_VMField(JVMCIObject name, JVMCIObject type, jlong offset, jlong address, JVMCIObject value, JVMCI_TRAPS) { + JavaThread* THREAD = JavaThread::current(); if (is_hotspot()) { - JavaThread* THREAD = JavaThread::current(); HotSpotJVMCI::VMField::klass()->initialize(CHECK_(JVMCIObject())); oop obj = HotSpotJVMCI::VMField::klass()->allocate_instance(CHECK_(JVMCIObject())); HotSpotJVMCI::VMField::set_name(this, obj, HotSpotJVMCI::resolve(name)); @@ -1263,7 +1189,7 @@ JVMCIObject JVMCIEnv::new_VMField(JVMCIObject name, JVMCIObject type, jlong offs HotSpotJVMCI::VMField::set_value(this, obj, HotSpotJVMCI::resolve(value)); return wrap(obj); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject result = jni()->NewObject(JNIJVMCI::VMField::clazz(), JNIJVMCI::VMField::constructor(), get_jobject(name), get_jobject(type), offset, address, get_jobject(value)); @@ -1272,8 +1198,8 @@ JVMCIObject JVMCIEnv::new_VMField(JVMCIObject name, JVMCIObject type, jlong offs } JVMCIObject JVMCIEnv::new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject value, JVMCI_TRAPS) { + JavaThread* THREAD = JavaThread::current(); if (is_hotspot()) { - JavaThread* THREAD = JavaThread::current(); HotSpotJVMCI::VMFlag::klass()->initialize(CHECK_(JVMCIObject())); oop obj = HotSpotJVMCI::VMFlag::klass()->allocate_instance(CHECK_(JVMCIObject())); HotSpotJVMCI::VMFlag::set_name(this, obj, HotSpotJVMCI::resolve(name)); @@ -1281,7 +1207,7 @@ JVMCIObject JVMCIEnv::new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject HotSpotJVMCI::VMFlag::set_value(this, obj, HotSpotJVMCI::resolve(value)); return wrap(obj); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject result = jni()->NewObject(JNIJVMCI::VMFlag::clazz(), JNIJVMCI::VMFlag::constructor(), get_jobject(name), get_jobject(type), get_jobject(value)); @@ -1290,8 +1216,8 @@ JVMCIObject JVMCIEnv::new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject } JVMCIObject JVMCIEnv::new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, JVMCI_TRAPS) { + JavaThread* THREAD = JavaThread::current(); if (is_hotspot()) { - JavaThread* THREAD = JavaThread::current(); HotSpotJVMCI::VMIntrinsicMethod::klass()->initialize(CHECK_(JVMCIObject())); oop obj = HotSpotJVMCI::VMIntrinsicMethod::klass()->allocate_instance(CHECK_(JVMCIObject())); HotSpotJVMCI::VMIntrinsicMethod::set_declaringClass(this, obj, HotSpotJVMCI::resolve(declaringClass)); @@ -1300,7 +1226,7 @@ JVMCIObject JVMCIEnv::new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObj HotSpotJVMCI::VMIntrinsicMethod::set_id(this, obj, id); return wrap(obj); } else { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject result = jni()->NewObject(JNIJVMCI::VMIntrinsicMethod::clazz(), JNIJVMCI::VMIntrinsicMethod::constructor(), get_jobject(declaringClass), get_jobject(name), get_jobject(descriptor), id); @@ -1346,7 +1272,7 @@ JVMCIObject JVMCIEnv::get_object_constant(oop objOop, bool compressed, bool dont return wrap(constant); } else { jlong handle = make_handle(obj); - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); jobject result = jni()->NewObject(JNIJVMCI::IndirectHotSpotObjectConstantImpl::clazz(), JNIJVMCI::IndirectHotSpotObjectConstantImpl::constructor(), handle, compressed, dont_register); @@ -1385,7 +1311,7 @@ JVMCIObject JVMCIEnv::wrap(jobject object) { jlong JVMCIEnv::make_handle(const Handle& obj) { assert(!obj.is_null(), "should only create handle for non-NULL oops"); - jobject handle = JVMCI::make_global(obj); + jobject handle = _runtime->make_global(obj); return (jlong) handle; } @@ -1399,15 +1325,15 @@ oop JVMCIEnv::resolve_handle(jlong objectHandle) { } JVMCIObject JVMCIEnv::create_string(const char* str, JVMCI_TRAPS) { + JavaThread* THREAD = JavaThread::current(); if (is_hotspot()) { - JavaThread* THREAD = JavaThread::current(); Handle result = java_lang_String::create_from_str(str, CHECK_(JVMCIObject())); return HotSpotJVMCI::wrap(result()); } else { jobject result; jboolean exception = false; { - JNIAccessMark jni(this); + JNIAccessMark jni(this, THREAD); result = jni()->NewStringUTF(str); exception = jni()->ExceptionCheck(); } diff --git a/src/hotspot/share/jvmci/jvmciEnv.hpp b/src/hotspot/share/jvmci/jvmciEnv.hpp index f92fd173d3f..a29e122f6bc 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.hpp +++ b/src/hotspot/share/jvmci/jvmciEnv.hpp @@ -35,6 +35,7 @@ class JVMCIObjectArray; class JVMCIPrimitiveArray; class JVMCICompiler; class JVMCIRuntime; +class nmethodLocker; #define JVMCI_EXCEPTION_CONTEXT \ JavaThread* thread=JavaThread::current(); \ @@ -44,8 +45,11 @@ class JVMCIRuntime; #define JVMCI_EXCEPTION_CHECK(env, ...) \ do { \ if (env->ExceptionCheck()) { \ - if (env != JavaThread::current()->jni_environment() && JVMCIEnv::get_shared_library_path() != NULL) { \ - tty->print_cr("In JVMCI shared library (%s):", JVMCIEnv::get_shared_library_path()); \ + if (env != JavaThread::current()->jni_environment()) { \ + char* sl_path; \ + if (::JVMCI::get_shared_library(sl_path, false) != NULL) { \ + tty->print_cr("In JVMCI shared library (%s):", sl_path); \ + } \ } \ tty->print_cr(__VA_ARGS__); \ return; \ @@ -143,16 +147,6 @@ class JVMCICompileState : public ResourceObj { class JVMCIEnv : public ResourceObj { friend class JNIAccessMark; - static char* _shared_library_path; // argument to os:dll_load - static void* _shared_library_handle; // result of os::dll_load - static JavaVM* _shared_library_javavm; // result of calling JNI_CreateJavaVM in shared library - - // Initializes the shared library JavaVM if not already initialized. - // Returns the JNI interface pointer for the current thread - // if initialization was performed by this call, NULL if - // initialization was performed by a previous call. - static JNIEnv* init_shared_library(JavaThread* thread); - // Initializes the _env, _mode and _runtime fields. void init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env); @@ -383,11 +377,21 @@ class JVMCIEnv : public ResourceObj { // These are analagous to the JNI routines JVMCIObject make_local(JVMCIObject object); - JVMCIObject make_global(JVMCIObject object); - JVMCIObject make_weak(JVMCIObject object); void destroy_local(JVMCIObject object); + + // Makes a JNI global handle that is not scoped by the + // lifetime of a JVMCIRuntime (cf JVMCIRuntime::make_global). + // These JNI handles are used when translating an object + // between the HotSpot and JVMCI shared library heap via + // HotSpotJVMCIRuntime.translate(Object) and + // HotSpotJVMCIRuntime.unhand(Class, long). Translation + // can happen in either direction so the referenced object + // can reside in either heap which is why JVMCIRuntime scoped + // handles cannot be used (they are specific to HotSpot heap objects). + JVMCIObject make_global(JVMCIObject object); + + // Destroys a JNI global handle created by JVMCIEnv::make_global. void destroy_global(JVMCIObject object); - void destroy_weak(JVMCIObject object); // Deoptimizes the nmethod (if any) in the HotSpotNmethod.address // field of mirror. The field is subsequently zeroed. @@ -399,9 +403,6 @@ class JVMCIEnv : public ResourceObj { JVMCICompileState* _compile_state; public: - static JavaVM* get_shared_library_javavm() { return _shared_library_javavm; } - static void* get_shared_library_handle() { return _shared_library_handle; } - static char* get_shared_library_path() { return _shared_library_path; } // Determines if this is for the JVMCI runtime in the HotSpot // heap (true) or the shared library heap (false). diff --git a/src/hotspot/share/jvmci/jvmciJavaClasses.cpp b/src/hotspot/share/jvmci/jvmciJavaClasses.cpp index ffaa2f083bc..770265f3c1e 100644 --- a/src/hotspot/share/jvmci/jvmciJavaClasses.cpp +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.cpp @@ -83,6 +83,7 @@ void HotSpotJVMCI::compute_offset(int &dest_offset, Klass* klass, const char* na // accessor itself does not include a class initialization check. ik->initialize(CHECK); } + JVMCI_event_2(" field offset for %s %s.%s = %d", signature, ik->external_name(), name, dest_offset); } #ifndef PRODUCT @@ -117,7 +118,8 @@ jmethodID JNIJVMCI::_HotSpotResolvedPrimitiveType_fromMetaspace_method; #define START_CLASS(className, fullClassName) { \ Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::fullClassName(), true, CHECK); \ - className::_klass = InstanceKlass::cast(k); \ + className::_klass = InstanceKlass::cast(k); \ + JVMCI_event_2(" klass for %s = " PTR_FORMAT, k->external_name(), p2i(k)); \ className::_klass->initialize(CHECK); #define END_CLASS } @@ -286,6 +288,7 @@ void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz, if (env->ExceptionCheck()) { return; } + jfieldID current = fieldid; if (static_field) { // Class initialization barrier fieldid = env->GetStaticFieldID(clazz, name, signature); @@ -293,6 +296,7 @@ void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz, // Class initialization barrier fieldid = env->GetFieldID(clazz, name, signature); } + JVMCI_event_2(" jfieldID for %s %s.%s = " PTR_FORMAT, signature, class_name, name, p2i(fieldid)); if (env->ExceptionCheck()) { env->ExceptionDescribe(); @@ -312,7 +316,9 @@ void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz, jclass k = env->FindClass(current_class_name); \ JVMCI_EXCEPTION_CHECK(env, "FindClass(%s)", current_class_name); \ assert(k != NULL, #fullClassName " not initialized"); \ - className::_class = (jclass) env->NewGlobalRef(k); \ + k = (jclass) env->NewGlobalRef(k); \ + JVMCI_event_2(" jclass for %s = " PTR_FORMAT, current_class_name, p2i(k)); \ + className::_class = k; \ } #define END_CLASS current_class_name = NULL; } @@ -329,14 +335,18 @@ void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz, #define STATIC_BOOLEAN_FIELD(className, name) FIELD(className, name, "Z", true) #define GET_JNI_METHOD(jniGetMethod, dst, clazz, methodName, signature) \ - if (JVMCILibDumpJNIConfig != NULL) { \ - fileStream* st = JVMCIGlobals::get_jni_config_file(); \ - st->print_cr("method %s %s %s", current_class_name, methodName, signature); \ - } else { \ - dst = env->jniGetMethod(clazz, methodName, signature); \ - JVMCI_EXCEPTION_CHECK(env, #jniGetMethod "(%s.%s%s)", current_class_name, methodName, signature); \ - assert(dst != NULL, "uninitialized"); \ - } + if (JVMCILibDumpJNIConfig != NULL) { \ + fileStream* st = JVMCIGlobals::get_jni_config_file(); \ + st->print_cr("method %s %s %s", current_class_name, methodName, signature); \ + } else { \ + jmethodID current = dst; \ + dst = env->jniGetMethod(clazz, methodName, signature); \ + JVMCI_EXCEPTION_CHECK(env, #jniGetMethod "(%s.%s%s)", \ + current_class_name, methodName, signature); \ + assert(dst != NULL, "uninitialized"); \ + JVMCI_event_2(" jmethodID for %s.%s%s = " PTR_FORMAT, \ + current_class_name, methodName, signature, p2i(dst)); \ + } #define GET_JNI_CONSTRUCTOR(clazz, signature) \ GET_JNI_METHOD(GetMethodID, JNIJVMCI::clazz::_constructor, clazz::_class, "", signature) \ @@ -493,30 +503,30 @@ void JNIJVMCI::initialize_ids(JNIEnv* env) { #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(f)) +} - if (env != JavaThread::current()->jni_environment()) { - jclass clazz = env->FindClass("jdk/vm/ci/hotspot/CompilerToVM"); +static void register_natives_for_class(JNIEnv* env, jclass clazz, const char* name, const JNINativeMethod *methods, jint nMethods) { + if (clazz == NULL) { + clazz = env->FindClass(name); if (env->ExceptionCheck()) { env->ExceptionDescribe(); - guarantee(false, "Could not find class jdk/vm/ci/hotspot/CompilerToVM"); - } - JNINativeMethod CompilerToVM_native_methods[] = { - { CC"registerNatives", CC"()V", FN_PTR(JVM_RegisterJVMCINatives) }, - }; - env->RegisterNatives(clazz, CompilerToVM_native_methods, 1); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - guarantee(false, ""); + fatal("Could not find class %s", name); } + } + env->RegisterNatives(clazz, methods, nMethods); + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + fatal("Failure registering natives for %s", name); + } +} - JNINativeMethod JVMCI_native_methods[] = { - { CC"initializeRuntime", CC"()Ljdk/vm/ci/runtime/JVMCIRuntime;", FN_PTR(JVM_GetJVMCIRuntime) }, - }; - env->RegisterNatives(JVMCI::clazz(), JVMCI_native_methods, 1); - if (env->ExceptionCheck()) { - env->ExceptionDescribe(); - guarantee(false, ""); - } +void JNIJVMCI::register_natives(JNIEnv* env) { + if (env != JavaThread::current()->jni_environment()) { + JNINativeMethod CompilerToVM_nmethods[] = {{ CC"registerNatives", CC"()V", FN_PTR(JVM_RegisterJVMCINatives) }}; + JNINativeMethod JVMCI_nmethods[] = {{ CC"initializeRuntime", CC"()Ljdk/vm/ci/runtime/JVMCIRuntime;", FN_PTR(JVM_GetJVMCIRuntime) }}; + + register_natives_for_class(env, NULL, "jdk/vm/ci/hotspot/CompilerToVM", CompilerToVM_nmethods, 1); + register_natives_for_class(env, JVMCI::clazz(), "jdk/vm/ci/runtime/JVMCI", JVMCI_nmethods, 1); } } diff --git a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp index aacac51dffd..fae548065a5 100644 --- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp @@ -124,7 +124,7 @@ object_field(HotSpotCompiledNmethod, installationFailureMessage, "Ljava/lang/String;") \ int_field(HotSpotCompiledNmethod, entryBCI) \ int_field(HotSpotCompiledNmethod, id) \ - long_field(HotSpotCompiledNmethod, compileState) \ + long_field(HotSpotCompiledNmethod, compileState) \ boolean_field(HotSpotCompiledNmethod, hasUnsafeAccess) \ end_class \ start_class(HotSpotForeignCallTarget, jdk_vm_ci_hotspot_HotSpotForeignCallTarget) \ @@ -544,7 +544,7 @@ class HotSpotJVMCI { static void check(JVMCIEnv* jvmciEnv, JVMCIObject obj, const char* field_name, jfieldID offset); \ static jclass _class; \ public: \ - static jclass clazz() { assert(_class != NULL, #fullClassName " uninitialized"); return _class; } \ + static jclass clazz() { assert(_class != NULL, #fullClassName " uninitialized"); return _class; } \ static jclass fullClassName ##_class() { assert(_class != NULL, "uninit"); return _class; } #undef METHOD @@ -639,6 +639,7 @@ class JNIJVMCI { static void initialize_ids(JNIEnv* env); static void initialize_field_id(JNIEnv* env, jfieldID &dest_offset, jclass klass, const char* klass_name, const char* name, const char* signature, bool static_field); + static void register_natives(JNIEnv* env); static jobject resolve_handle(JVMCIObject obj) { return obj.as_jobject(); } static JVMCIObject wrap(jobject obj) { return JVMCIObject(obj, false); } diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index e603452618f..35e19cfa469 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -25,9 +25,12 @@ #include "classfile/javaClasses.inline.hpp" #include "classfile/symbolTable.hpp" #include "compiler/compileBroker.hpp" +#include "gc/shared/oopStorage.inline.hpp" +#include "gc/shared/oopStorageSet.hpp" #include "jvmci/jniAccessMark.inline.hpp" #include "jvmci/jvmciCompilerToVM.hpp" #include "jvmci/jvmciRuntime.hpp" +#include "jvmci/metadataHandles.hpp" #include "logging/log.hpp" #include "memory/oopFactory.hpp" #include "memory/universe.hpp" @@ -35,11 +38,13 @@ #include "oops/method.inline.hpp" #include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" +#include "oops/typeArrayOop.inline.hpp" #include "runtime/atomic.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/deoptimization.hpp" #include "runtime/fieldDescriptor.inline.hpp" #include "runtime/frame.inline.hpp" +#include "runtime/jniHandles.inline.hpp" #include "runtime/sharedRuntime.hpp" #if INCLUDE_G1GC #include "gc/g1/g1ThreadLocalData.hpp" @@ -705,6 +710,178 @@ void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) { } } +JVMCIRuntime::JVMCIRuntime(int id) { + _init_state = uninitialized; + _shared_library_javavm = NULL; + _id = id; + _metadata_handles = new MetadataHandles(); + JVMCI_event_1("created new JVMCI runtime %d (" PTR_FORMAT ")", id, p2i(this)); +} + +// Handles to objects in the Hotspot heap. +static OopStorage* object_handles() { + return OopStorageSet::vm_global(); +} + +jobject JVMCIRuntime::make_global(const Handle& obj) { + assert(!Universe::heap()->is_gc_active(), "can't extend the root set during GC"); + assert(oopDesc::is_oop(obj()), "not an oop"); + oop* ptr = object_handles()->allocate(); + jobject res = NULL; + if (ptr != NULL) { + assert(*ptr == NULL, "invariant"); + NativeAccess<>::oop_store(ptr, obj()); + res = reinterpret_cast(ptr); + } else { + vm_exit_out_of_memory(sizeof(oop), OOM_MALLOC_ERROR, + "Cannot create JVMCI oop handle"); + } + MutexLocker ml(JVMCI_lock); + return res; +} + +void JVMCIRuntime::destroy_global(jobject handle) { + // Assert before nulling out, for better debugging. + assert(is_global_handle(handle), "precondition"); + oop* oop_ptr = reinterpret_cast(handle); + NativeAccess<>::oop_store(oop_ptr, (oop)NULL); + object_handles()->release(oop_ptr); + MutexLocker ml(JVMCI_lock); +} + +bool JVMCIRuntime::is_global_handle(jobject handle) { + const oop* ptr = reinterpret_cast(handle); + return object_handles()->allocation_status(ptr) == OopStorage::ALLOCATED_ENTRY; +} + +jmetadata JVMCIRuntime::allocate_handle(const methodHandle& handle) { + MutexLocker ml(JVMCI_lock); + return _metadata_handles->allocate_handle(handle); +} + +jmetadata JVMCIRuntime::allocate_handle(const constantPoolHandle& handle) { + MutexLocker ml(JVMCI_lock); + return _metadata_handles->allocate_handle(handle); +} + +void JVMCIRuntime::release_handle(jmetadata handle) { + MutexLocker ml(JVMCI_lock); + _metadata_handles->chain_free_list(handle); +} + +// Function for redirecting shared library JavaVM output to tty +static void _log(const char* buf, size_t count) { + tty->write((char*) buf, count); +} + +// Function for shared library JavaVM to flush tty +static void _flush_log() { + tty->flush(); +} + +// Function for shared library JavaVM to exit HotSpot on a fatal error +static void _fatal() { + fatal("Fatal error in JVMCI shared library"); +} + +JNIEnv* JVMCIRuntime::init_shared_library_javavm() { + JavaVM* javaVM = (JavaVM*) _shared_library_javavm; + if (javaVM == NULL) { + MutexLocker locker(JVMCI_lock); + // Check again under JVMCI_lock + javaVM = (JavaVM*) _shared_library_javavm; + if (javaVM != NULL) { + return NULL; + } + char* sl_path; + void* sl_handle = JVMCI::get_shared_library(sl_path, true); + + jint (*JNI_CreateJavaVM)(JavaVM **pvm, void **penv, void *args); + typedef jint (*JNI_CreateJavaVM_t)(JavaVM **pvm, void **penv, void *args); + + JNI_CreateJavaVM = CAST_TO_FN_PTR(JNI_CreateJavaVM_t, os::dll_lookup(sl_handle, "JNI_CreateJavaVM")); + if (JNI_CreateJavaVM == NULL) { + vm_exit_during_initialization("Unable to find JNI_CreateJavaVM", sl_path); + } + + ResourceMark rm; + JavaVMInitArgs vm_args; + vm_args.version = JNI_VERSION_1_2; + vm_args.ignoreUnrecognized = JNI_TRUE; + JavaVMOption options[4]; + jlong javaVM_id = 0; + + // Protocol: JVMCI shared library JavaVM should support a non-standard "_javavm_id" + // option whose extraInfo info field is a pointer to which a unique id for the + // JavaVM should be written. + options[0].optionString = (char*) "_javavm_id"; + options[0].extraInfo = &javaVM_id; + + options[1].optionString = (char*) "_log"; + options[1].extraInfo = (void*) _log; + options[2].optionString = (char*) "_flush_log"; + options[2].extraInfo = (void*) _flush_log; + options[3].optionString = (char*) "_fatal"; + options[3].extraInfo = (void*) _fatal; + + vm_args.version = JNI_VERSION_1_2; + vm_args.options = options; + vm_args.nOptions = sizeof(options) / sizeof(JavaVMOption); + + JNIEnv* env = NULL; + int result = (*JNI_CreateJavaVM)(&javaVM, (void**) &env, &vm_args); + if (result == JNI_OK) { + guarantee(env != NULL, "missing env"); + _shared_library_javavm = javaVM; + JVMCI_event_1("created JavaVM[%ld]@" PTR_FORMAT " for JVMCI runtime %d", javaVM_id, p2i(javaVM), _id); + return env; + } else { + vm_exit_during_initialization(err_msg("JNI_CreateJavaVM failed with return value %d", result), sl_path); + } + } + return NULL; +} + +void JVMCIRuntime::init_JavaVM_info(jlongArray info, JVMCI_TRAPS) { + if (info != NULL) { + typeArrayOop info_oop = (typeArrayOop) JNIHandles::resolve(info); + if (info_oop->length() < 4) { + JVMCI_THROW_MSG(ArrayIndexOutOfBoundsException, err_msg("%d < 4", info_oop->length())); + } + JavaVM* javaVM = (JavaVM*) _shared_library_javavm; + info_oop->long_at_put(0, (jlong) (address) javaVM); + info_oop->long_at_put(1, (jlong) (address) javaVM->functions->reserved0); + info_oop->long_at_put(2, (jlong) (address) javaVM->functions->reserved1); + info_oop->long_at_put(3, (jlong) (address) javaVM->functions->reserved2); + } +} + +#define JAVAVM_CALL_BLOCK \ + guarantee(thread != NULL && _shared_library_javavm != NULL, "npe"); \ + ThreadToNativeFromVM ttnfv(thread); \ + JavaVM* javavm = (JavaVM*) _shared_library_javavm; + +jint JVMCIRuntime::AttachCurrentThread(JavaThread* thread, void **penv, void *args) { + JAVAVM_CALL_BLOCK + return javavm->AttachCurrentThread(penv, args); +} + +jint JVMCIRuntime::AttachCurrentThreadAsDaemon(JavaThread* thread, void **penv, void *args) { + JAVAVM_CALL_BLOCK + return javavm->AttachCurrentThreadAsDaemon(penv, args); +} + +jint JVMCIRuntime::DetachCurrentThread(JavaThread* thread) { + JAVAVM_CALL_BLOCK + return javavm->DetachCurrentThread(); +} + +jint JVMCIRuntime::GetEnv(JavaThread* thread, void **penv, jint version) { + JAVAVM_CALL_BLOCK + return javavm->GetEnv(penv, version); +} +#undef JAVAVM_CALL_BLOCK \ + void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(JVMCI_TRAPS) { if (is_HotSpotJVMCIRuntime_initialized()) { if (JVMCIENV->is_hotspot() && UseJVMCINativeLibrary) { @@ -718,29 +895,32 @@ void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(JVMCI_TRAPS) { JVMCIObject result = JVMCIENV->call_HotSpotJVMCIRuntime_runtime(JVMCI_CHECK); _HotSpotJVMCIRuntime_instance = JVMCIENV->make_global(result); + JVMCI::_is_initialized = true; } void JVMCIRuntime::initialize(JVMCIEnv* JVMCIENV) { - assert(this != NULL, "sanity"); // Check first without JVMCI_lock - if (_initialized) { + if (_init_state == fully_initialized) { return; } MutexLocker locker(JVMCI_lock); // Check again under JVMCI_lock - if (_initialized) { + if (_init_state == fully_initialized) { return; } - while (_being_initialized) { + while (_init_state == being_initialized) { + JVMCI_event_1("waiting for initialization of JVMCI runtime %d", _id); JVMCI_lock->wait(); - if (_initialized) { + if (_init_state == fully_initialized) { + JVMCI_event_1("done waiting for initialization of JVMCI runtime %d", _id); return; } } - _being_initialized = true; + JVMCI_event_1("initializing JVMCI runtime %d", _id); + _init_state = being_initialized; { MutexUnlocker unlock(JVMCI_lock); @@ -759,6 +939,11 @@ void JVMCIRuntime::initialize(JVMCIEnv* JVMCIENV) { fatal("JNI exception during init"); } } + + if (!JVMCIENV->is_hotspot()) { + JNIAccessMark jni(JVMCIENV, THREAD); + JNIJVMCI::register_natives(jni.env()); + } create_jvmci_primitive_type(T_BOOLEAN, JVMCI_CHECK_EXIT_((void)0)); create_jvmci_primitive_type(T_BYTE, JVMCI_CHECK_EXIT_((void)0)); create_jvmci_primitive_type(T_CHAR, JVMCI_CHECK_EXIT_((void)0)); @@ -774,8 +959,8 @@ void JVMCIRuntime::initialize(JVMCIEnv* JVMCIENV) { } } - _initialized = true; - _being_initialized = false; + _init_state = fully_initialized; + JVMCI_event_1("initialized JVMCI runtime %d", _id); JVMCI_lock->notify_all(); } @@ -817,8 +1002,7 @@ JVMCIObject JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_TRAPS) { return _HotSpotJVMCIRuntime_instance; } - -// private void CompilerToVM.registerNatives() +// private static void CompilerToVM.registerNatives() JVM_ENTRY_NO_ENV(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass)) JNI_JVMCIENV(thread, env); @@ -854,16 +1038,17 @@ JVM_END void JVMCIRuntime::shutdown() { - if (is_HotSpotJVMCIRuntime_initialized()) { - _shutdown_called = true; - - THREAD_JVMCIENV(JavaThread::current()); + if (_HotSpotJVMCIRuntime_instance.is_non_null()) { + JVMCI_event_1("shutting down HotSpotJVMCIRuntime for JVMCI runtime %d", _id); + JVMCIEnv __stack_jvmci_env__(JavaThread::current(), _HotSpotJVMCIRuntime_instance.is_hotspot(), __FILE__, __LINE__); + JVMCIEnv* JVMCIENV = &__stack_jvmci_env__; JVMCIENV->call_HotSpotJVMCIRuntime_shutdown(_HotSpotJVMCIRuntime_instance); + JVMCI_event_1("shut down HotSpotJVMCIRuntime for JVMCI runtime %d", _id); } } void JVMCIRuntime::bootstrap_finished(TRAPS) { - if (is_HotSpotJVMCIRuntime_initialized()) { + if (_HotSpotJVMCIRuntime_instance.is_non_null()) { THREAD_JVMCIENV(JavaThread::current()); JVMCIENV->call_HotSpotJVMCIRuntime_bootstrapFinished(_HotSpotJVMCIRuntime_instance, JVMCIENV); } @@ -1290,10 +1475,10 @@ void JVMCIRuntime::compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, c if (compiler->is_bootstrapping() && is_osr) { // no OSR compilations during bootstrap - the compiler is just too slow at this point, // and we know that there are no endless loops - compile_state->set_failure(true, "No OSR during boostrap"); + compile_state->set_failure(true, "No OSR during bootstrap"); return; } - if (JVMCI::shutdown_called()) { + if (JVMCI::in_shutdown()) { compile_state->set_failure(false, "Avoiding compilation during shutdown"); return; } diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index 27e7abb2257..bc3fd45bf95 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -28,10 +28,12 @@ #include "jvmci/jvmci.hpp" #include "jvmci/jvmciExceptions.hpp" #include "jvmci/jvmciObject.hpp" +#include "utilities/linkedlist.hpp" class JVMCIEnv; class JVMCICompiler; class JVMCICompileState; +class MetadataHandles; // Encapsulates the JVMCI metadata for an nmethod. // JVMCINMethodData objects are inlined into nmethods @@ -86,6 +88,7 @@ class JVMCINMethodData { // A top level class that represents an initialized JVMCI runtime. // There is one instance of this class per HotSpotJVMCIRuntime object. class JVMCIRuntime: public CHeapObj { + friend class JVMCI; public: // Constants describing whether JVMCI wants to be able to adjust the compilation // level selected for a method by the VM compilation policy and if so, based on @@ -97,12 +100,33 @@ class JVMCIRuntime: public CHeapObj { }; private: - volatile bool _being_initialized; - volatile bool _initialized; + enum InitState { + uninitialized, + being_initialized, + fully_initialized + }; + + // Initialization state of this JVMCIRuntime. + InitState _init_state; + + // A wrapper for a VM scoped JNI global handle (i.e. JVMCIEnv::make_global) + // to a HotSpotJVMCIRuntime instance. This JNI global handle must never + // be explicitly destroyed as it can be accessed in a racy way during + // JVMCI shutdown. Furthermore, it will be reclaimed when + // the VM or shared library JavaVM managing the handle dies. JVMCIObject _HotSpotJVMCIRuntime_instance; - bool _shutdown_called; + // Result of calling JNI_CreateJavaVM in the JVMCI shared library. + // Must only be modified under JVMCI_lock. + volatile JavaVM* _shared_library_javavm; + + // The HotSpot heap based runtime will have an id of -1 and the + // JVMCI shared library runtime will have an id of 0. + int _id; + + // Handles to Metadata objects. + MetadataHandles* _metadata_handles; JVMCIObject create_jvmci_primitive_type(BasicType type, JVMCI_TRAPS); @@ -131,44 +155,79 @@ class JVMCIRuntime: public CHeapObj { constantTag tag); public: - JVMCIRuntime() { - _initialized = false; - _being_initialized = false; - _shutdown_called = false; - } - - /** - * Compute offsets and construct any state required before executing JVMCI code. - */ + JVMCIRuntime(int id); + + int id() const { return _id; } + + // Ensures that a JVMCI shared library JavaVM exists for this runtime. + // If the JavaVM was created by this call, then the thread-local JNI + // interface pointer for the JavaVM is returned otherwise NULL is returned. + JNIEnv* init_shared_library_javavm(); + + // Determines if the JVMCI shared library JavaVM exists for this runtime. + bool has_shared_library_javavm() { return _shared_library_javavm != NULL; } + + // Copies info about the JVMCI shared library JavaVM associated with this + // runtime into `info` as follows: + // { + // javaVM, // the {@code JavaVM*} value + // javaVM->functions->reserved0, + // javaVM->functions->reserved1, + // javaVM->functions->reserved2 + // } + void init_JavaVM_info(jlongArray info, JVMCI_TRAPS); + + // Wrappers for calling Invocation Interface functions on the + // JVMCI shared library JavaVM associated with this runtime. + // These wrappers ensure all required thread state transitions are performed. + jint AttachCurrentThread(JavaThread* thread, void **penv, void *args); + jint AttachCurrentThreadAsDaemon(JavaThread* thread, void **penv, void *args); + jint DetachCurrentThread(JavaThread* thread); + jint GetEnv(JavaThread* thread, void **penv, jint version); + + // Compute offsets and construct any state required before executing JVMCI code. void initialize(JVMCIEnv* jvmciEnv); - /** - * Gets the singleton HotSpotJVMCIRuntime instance, initializing it if necessary - */ + // Allocation and management of JNI global object handles + // whose lifetime is scoped by this JVMCIRuntime. The lifetime + // of these handles is the same as the JVMCI shared library JavaVM + // associated with this JVMCIRuntime. These JNI handles are + // used when creating a IndirectHotSpotObjectConstantImpl in the + // shared library JavaVM. + jobject make_global(const Handle& obj); + void destroy_global(jobject handle); + bool is_global_handle(jobject handle); + + // Allocation and management of metadata handles. + jmetadata allocate_handle(const methodHandle& handle); + jmetadata allocate_handle(const constantPoolHandle& handle); + void release_handle(jmetadata handle); + + // Gets the HotSpotJVMCIRuntime instance for this runtime, + // initializing it first if necessary. JVMCIObject get_HotSpotJVMCIRuntime(JVMCI_TRAPS); bool is_HotSpotJVMCIRuntime_initialized() { return _HotSpotJVMCIRuntime_instance.is_non_null(); } - /** - * Trigger initialization of HotSpotJVMCIRuntime through JVMCI.getRuntime() - */ + // Gets the current HotSpotJVMCIRuntime instance for this runtime which + // may be a "null" JVMCIObject value. + JVMCIObject probe_HotSpotJVMCIRuntime() { + return _HotSpotJVMCIRuntime_instance; + } + + // Trigger initialization of HotSpotJVMCIRuntime through JVMCI.getRuntime() void initialize_JVMCI(JVMCI_TRAPS); - /** - * Explicitly initialize HotSpotJVMCIRuntime itself - */ + // Explicitly initialize HotSpotJVMCIRuntime itself void initialize_HotSpotJVMCIRuntime(JVMCI_TRAPS); void call_getCompiler(TRAPS); + // Shuts down this runtime by calling HotSpotJVMCIRuntime.shutdown(). void shutdown(); - bool shutdown_called() { - return _shutdown_called; - } - void bootstrap_finished(TRAPS); // Look up a klass by name from a particular class loader (the accessor's). @@ -222,7 +281,7 @@ class JVMCIRuntime: public CHeapObj { int frame_words, OopMapSet* oop_map_set, ExceptionHandlerTable* handler_table, - ImplicitExceptionTable* implicit_exception_table, + ImplicitExceptionTable* implicit_exception_table, AbstractCompiler* compiler, DebugInformationRecorder* debug_info, Dependencies* dependencies, @@ -235,9 +294,7 @@ class JVMCIRuntime: public CHeapObj { char* speculations, int speculations_len); - /** - * Exits the VM due to an unexpected exception. - */ + // Exits the VM due to an unexpected exception. static void exit_on_pending_exception(JVMCIEnv* JVMCIENV, const char* message); static void describe_pending_hotspot_exception(JavaThread* THREAD, bool clear); @@ -340,19 +397,4 @@ class JVMCIRuntime: public CHeapObj { // Test only function static jint test_deoptimize_call_int(JavaThread* thread, int value); }; - -// Tracing macros. - -#define IF_TRACE_jvmci_1 if (!(JVMCITraceLevel >= 1)) ; else -#define IF_TRACE_jvmci_2 if (!(JVMCITraceLevel >= 2)) ; else -#define IF_TRACE_jvmci_3 if (!(JVMCITraceLevel >= 3)) ; else -#define IF_TRACE_jvmci_4 if (!(JVMCITraceLevel >= 4)) ; else -#define IF_TRACE_jvmci_5 if (!(JVMCITraceLevel >= 5)) ; else - -#define TRACE_jvmci_1 if (!(JVMCITraceLevel >= 1 && (tty->print(PTR_FORMAT " JVMCITrace-1: ", p2i(JavaThread::current())), true))) ; else tty->print_cr -#define TRACE_jvmci_2 if (!(JVMCITraceLevel >= 2 && (tty->print(PTR_FORMAT " JVMCITrace-2: ", p2i(JavaThread::current())), true))) ; else tty->print_cr -#define TRACE_jvmci_3 if (!(JVMCITraceLevel >= 3 && (tty->print(PTR_FORMAT " JVMCITrace-3: ", p2i(JavaThread::current())), true))) ; else tty->print_cr -#define TRACE_jvmci_4 if (!(JVMCITraceLevel >= 4 && (tty->print(PTR_FORMAT " JVMCITrace-4: ", p2i(JavaThread::current())), true))) ; else tty->print_cr -#define TRACE_jvmci_5 if (!(JVMCITraceLevel >= 5 && (tty->print(PTR_FORMAT " JVMCITrace-5: ", p2i(JavaThread::current())), true))) ; else tty->print_cr - #endif // SHARE_JVMCI_JVMCIRUNTIME_HPP diff --git a/src/hotspot/share/jvmci/jvmci_globals.cpp b/src/hotspot/share/jvmci/jvmci_globals.cpp index 6963af8a33f..bcfde2aefbc 100644 --- a/src/hotspot/share/jvmci/jvmci_globals.cpp +++ b/src/hotspot/share/jvmci/jvmci_globals.cpp @@ -108,6 +108,7 @@ bool JVMCIGlobals::check_jvmci_flags_are_consistent() { } JVMCI_FLAG_CHECKED(EagerJVMCI) + CHECK_NOT_SET(JVMCIEventLogLevel, EnableJVMCI) CHECK_NOT_SET(JVMCITraceLevel, EnableJVMCI) CHECK_NOT_SET(JVMCICounterSize, EnableJVMCI) CHECK_NOT_SET(JVMCICountersExcludeCompiler, EnableJVMCI) @@ -166,6 +167,8 @@ bool JVMCIGlobals::enable_jvmci_product_mode(JVMFlag::Flags origin) { "JVMCICounterSize", "JVMCICountersExcludeCompiler", "JVMCINMethodSizeLimit", + "JVMCIEventLogLevel", + "JVMCITraceLevel", "JVMCILibPath", "JVMCILibDumpJNIConfig", "UseJVMCINativeLibrary", diff --git a/src/hotspot/share/jvmci/jvmci_globals.hpp b/src/hotspot/share/jvmci/jvmci_globals.hpp index 16a56c46d1c..f4ae52b8473 100644 --- a/src/hotspot/share/jvmci/jvmci_globals.hpp +++ b/src/hotspot/share/jvmci/jvmci_globals.hpp @@ -90,11 +90,13 @@ class fileStream; NOT_COMPILER2(product(bool, ReduceInitialCardMarks, true, \ "Defer write barriers of young objects")) \ \ + experimental(intx, JVMCIEventLogLevel, 1, \ + "Event log level for JVMCI") \ + range(0, 4) \ + \ experimental(intx, JVMCITraceLevel, 0, \ - "Trace level for JVMCI: " \ - "1 means emit a message for each CompilerToVM call," \ - "levels greater than 1 provide progressively greater detail") \ - range(0, 6) \ + "Trace level for JVMCI") \ + range(0, 4) \ \ experimental(intx, JVMCICounterSize, 0, \ "Reserved size for benchmark counters") \ diff --git a/src/hotspot/share/jvmci/metadataHandleBlock.cpp b/src/hotspot/share/jvmci/metadataHandles.cpp similarity index 73% rename from src/hotspot/share/jvmci/metadataHandleBlock.cpp rename to src/hotspot/share/jvmci/metadataHandles.cpp index 83b291a9081..da1ad7b61a0 100644 --- a/src/hotspot/share/jvmci/metadataHandleBlock.cpp +++ b/src/hotspot/share/jvmci/metadataHandles.cpp @@ -22,19 +22,17 @@ */ #include "precompiled.hpp" -#include "jvmci/metadataHandleBlock.hpp" +#include "jvmci/metadataHandles.hpp" #include "runtime/atomic.hpp" -MetadataHandleBlock* MetadataHandleBlock::_last = NULL; -intptr_t MetadataHandleBlock::_free_list = 0; -int MetadataHandleBlock::_allocate_before_rebuild = 0; - -jmetadata MetadataHandleBlock::allocate_metadata_handle(Metadata* obj) { +jmetadata MetadataHandles::allocate_metadata_handle(Metadata* obj) { assert(obj->is_valid() && obj->is_metadata(), "must be"); - if (_last == NULL) { + if (_head == NULL) { // This is the first allocation. - _last = this; + _head = new MetadataHandleBlock(); + _last = _head; + _num_blocks++; } HandleRecord* handle = get_handle(); @@ -47,7 +45,7 @@ jmetadata MetadataHandleBlock::allocate_metadata_handle(Metadata* obj) { return (jmetadata) handle; } - // Check if unused block follow last + // Check if an unused block follows last if (_last->_next != NULL) { // update last and retry _last = _last->_next; @@ -56,23 +54,23 @@ jmetadata MetadataHandleBlock::allocate_metadata_handle(Metadata* obj) { // No space available, we have to rebuild free list or expand if (_allocate_before_rebuild == 0) { - rebuild_free_list(); // updates _allocate_before_rebuild counter + rebuild_free_list(); // updates _allocate_before_rebuild counter } else { // Append new block - // This can block, but the caller has a metadata handle around this object. - _last->_next = allocate_block(); + _last->_next = new MetadataHandleBlock(); _last = _last->_next; _allocate_before_rebuild--; + _num_blocks++; } return allocate_metadata_handle(obj); // retry } -void MetadataHandleBlock::rebuild_free_list() { +void MetadataHandles::rebuild_free_list() { assert(_allocate_before_rebuild == 0 && _free_list == 0, "just checking"); int free = 0; int blocks = 0; - for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) { + for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) { for (int index = 0; index < current->_top; index++) { HandleRecord* handle = &(current->_handles)[index]; if (handle->value() == NULL) { @@ -82,34 +80,48 @@ void MetadataHandleBlock::rebuild_free_list() { } } // we should not rebuild free list if there are unused handles at the end - assert(current->_top == block_size_in_handles, "just checking"); + assert(current->_top == MetadataHandleBlock::block_size_in_handles, "just checking"); blocks++; } + assert(_num_blocks == blocks, "%d != %d", _num_blocks, blocks); + assert(_num_free_handles == free, "%d != %d", _num_free_handles, free); // Heuristic: if more than half of the handles are NOT free we rebuild next time // as well, otherwise we append a corresponding number of new blocks before // attempting a free list rebuild again. - int total = blocks * block_size_in_handles; + int total = blocks * MetadataHandleBlock::block_size_in_handles; int extra = total - 2*free; if (extra > 0) { // Not as many free handles as we would like - compute number of new blocks to append - _allocate_before_rebuild = (extra + block_size_in_handles - 1) / block_size_in_handles; + _allocate_before_rebuild = (extra + MetadataHandleBlock::block_size_in_handles - 1) / MetadataHandleBlock::block_size_in_handles; + } +} + +void MetadataHandles::clear() { + _free_list = 0; + _last = _head; + if (_head != NULL) { + for (MetadataHandleBlock* block = _head; block != NULL; block = block->_next) { + block->_top = 0; + } } + _num_handles = 0; + _num_free_handles = 0; } -void MetadataHandleBlock::metadata_do(void f(Metadata*)) { - for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) { +void MetadataHandles::metadata_do(void f(Metadata*)) { + for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) { for (int index = 0; index < current->_top; index++) { HandleRecord* root = &(current->_handles)[index]; Metadata* value = root->value(); // traverse heap pointers only, not deleted handles or free list // pointers if (value != NULL && ((intptr_t) value & ptr_tag) == 0) { - assert(value->is_valid(), "invalid metadata %s", get_name(index)); + assert(value->is_valid(), "invalid metadata %s", current->get_name(index)); f(value); } } // the next handle block is valid only if current block is full - if (current->_top < block_size_in_handles) { + if (current->_top < MetadataHandleBlock::block_size_in_handles) { break; } } @@ -117,8 +129,8 @@ void MetadataHandleBlock::metadata_do(void f(Metadata*)) { // Visit any live metadata handles and clean them up. Since clearing of these handles is driven by // weak references they will be cleared at some point in the future when the reference cleaning logic is run. -void MetadataHandleBlock::do_unloading() { - for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) { +void MetadataHandles::do_unloading() { + for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) { for (int index = 0; index < current->_top; index++) { HandleRecord* handle = &(current->_handles)[index]; Metadata* value = handle->value(); @@ -152,7 +164,7 @@ void MetadataHandleBlock::do_unloading() { } } // the next handle block is valid only if current block is full - if (current->_top < block_size_in_handles) { + if (current->_top < MetadataHandleBlock::block_size_in_handles) { break; } } diff --git a/src/hotspot/share/jvmci/metadataHandleBlock.hpp b/src/hotspot/share/jvmci/metadataHandles.hpp similarity index 76% rename from src/hotspot/share/jvmci/metadataHandleBlock.hpp rename to src/hotspot/share/jvmci/metadataHandles.hpp index 0c6d6ddc366..f47ff4f085e 100644 --- a/src/hotspot/share/jvmci/metadataHandleBlock.hpp +++ b/src/hotspot/share/jvmci/metadataHandles.hpp @@ -21,8 +21,8 @@ * questions. */ -#ifndef SHARE_JVMCI_METADATAHANDLEBLOCK_HPP -#define SHARE_JVMCI_METADATAHANDLEBLOCK_HPP +#ifndef SHARE_JVMCI_METADATAHANDLES_HPP +#define SHARE_JVMCI_METADATAHANDLES_HPP #include "oops/constantPool.hpp" #include "oops/metadata.hpp" @@ -72,22 +72,15 @@ struct _jmetadata { typedef struct _jmetadata HandleRecord; typedef struct _jmetadata *jmetadata; +class MetadataHandles; -// JVMCI maintains direct references to metadata. To make these references safe in the face of -// class redefinition, they are held in handles so they can be scanned during GC. They are -// managed in a cooperative way between the Java code and HotSpot. A handle is filled in and -// passed back to the Java code which is responsible for setting the handle to NULL when it -// is no longer in use. This is done by jdk.vm.ci.hotspot.HandleCleaner. The -// rebuild_free_list function notices when the handle is clear and reclaims it for re-use. class MetadataHandleBlock : public CHeapObj { + friend class MetadataHandles; private: enum SomeConstants { - block_size_in_handles = 32, // Number of handles per handle block - ptr_tag = 1, - ptr_mask = ~((intptr_t)ptr_tag) + block_size_in_handles = 32 // Number of handles per handle block }; - // Free handles always have their low bit set so those pointers can // be distinguished from handles which are in use. The last handle // on the free list has a NULL pointer with the tag bit set, so it's @@ -98,12 +91,6 @@ class MetadataHandleBlock : public CHeapObj { int _top; // Index of next unused handle MetadataHandleBlock* _next; // Link to next block - // The following instance variables are only used by the first block in a chain. - // Having two types of blocks complicates the code and the space overhead is negligible. - static MetadataHandleBlock* _last; // Last block in use - static intptr_t _free_list; // Handle free list - static int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list - MetadataHandleBlock() { _top = 0; _next = NULL; @@ -121,20 +108,42 @@ class MetadataHandleBlock : public CHeapObj { return ""; #endif } +}; - static HandleRecord* get_free_handle() { - assert(_free_list != 0, "should check before calling"); +// JVMCI maintains direct references to metadata. To make these references safe in the face of +// class redefinition, they are held in handles so they can be scanned during GC. They are +// managed in a cooperative way between the Java code and HotSpot. A handle is filled in and +// passed back to the Java code which is responsible for setting the handle to NULL when it +// is no longer in use. This is done by jdk.vm.ci.hotspot.HandleCleaner. The +// rebuild_free_list function notices when the handle is clear and reclaims it for re-use. +class MetadataHandles : public CHeapObj { + private: + enum SomeConstants { + ptr_tag = 1, + ptr_mask = ~((intptr_t)ptr_tag) + }; + + MetadataHandleBlock* _head; // First block + MetadataHandleBlock* _last; // Last block in use + intptr_t _free_list; // Handle free list + int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list + int _num_blocks; // Number of blocks + int _num_handles; + int _num_free_handles; + + HandleRecord* get_free_handle() { HandleRecord* handle = (HandleRecord*) (_free_list & ptr_mask); _free_list = (ptr_mask & (intptr_t) (handle->value())); assert(_free_list != ptr_tag, "should be null"); - handle->set_value(NULL); + _num_free_handles--; return handle; } - static HandleRecord* get_handle() { + HandleRecord* get_handle() { assert(_last != NULL, "sanity"); // Try last block - if (_last->_top < block_size_in_handles) { + if (_last->_top < MetadataHandleBlock::block_size_in_handles) { + _num_handles++; return &(_last->_handles)[_last->_top++]; } else if (_free_list != 0) { // Try free list @@ -148,23 +157,39 @@ class MetadataHandleBlock : public CHeapObj { jmetadata allocate_metadata_handle(Metadata* metadata); public: + MetadataHandles() { + _head = NULL; + _last = NULL; + _free_list = 0; + _allocate_before_rebuild = 0; + _num_blocks = 0; + _num_handles = 0; + _num_free_handles = 0; + } + + int num_handles() const { return _num_handles; } + int num_free_handles() const { return _num_free_handles; } + int num_blocks() const { return _num_blocks; } + jmetadata allocate_handle(const methodHandle& handle) { return allocate_metadata_handle(handle()); } jmetadata allocate_handle(const constantPoolHandle& handle) { return allocate_metadata_handle(handle()); } - static MetadataHandleBlock* allocate_block() { return new MetadataHandleBlock(); } - - // Adds `handle` to the free list in this block - static void chain_free_list(HandleRecord* handle) { + // Adds `handle` to the free list + void chain_free_list(HandleRecord* handle) { handle->set_value((Metadata*) (ptr_tag | _free_list)); #ifdef METADATA_TRACK_NAMES handle->set_name(NULL); #endif _free_list = (intptr_t) handle; + _num_free_handles++; } + // Clears all handles without releasing any handle memory. + void clear(); + void metadata_do(void f(Metadata*)); void do_unloading(); }; -#endif // SHARE_JVMCI_METADATAHANDLEBLOCK_HPP +#endif // SHARE_JVMCI_METADATAHANDLES_HPP diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 5f514b76f75..16e1820d065 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "code/codeCache.hpp" #include "compiler/compileBroker.hpp" #include "gc/shared/collectedHeap.hpp" #include "jvmci/jvmciCodeInstaller.hpp" diff --git a/src/hotspot/share/memory/dynamicArchive.cpp b/src/hotspot/share/memory/dynamicArchive.cpp index 774f311fbd3..578c35dc5c3 100644 --- a/src/hotspot/share/memory/dynamicArchive.cpp +++ b/src/hotspot/share/memory/dynamicArchive.cpp @@ -484,9 +484,9 @@ class DynamicArchiveBuilder : ResourceObj { p2i(obj), p2i(p), bytes, MetaspaceObj::type_name(ref->msotype())); memcpy(p, obj, bytes); - intptr_t* cloned_vtable = MetaspaceShared::fix_cpp_vtable_for_dynamic_archive(ref->msotype(), p); - if (cloned_vtable != NULL) { - update_pointer((address*)p, (address)cloned_vtable, "vtb", 0, /*is_mso_pointer*/false); + intptr_t* archived_vtable = MetaspaceShared::get_archived_cpp_vtable(ref->msotype(), p); + if (archived_vtable != NULL) { + update_pointer((address*)p, (address)archived_vtable, "vtb", 0, /*is_mso_pointer*/false); mark_pointer((address*)p); } diff --git a/src/hotspot/share/memory/metaspaceShared.cpp b/src/hotspot/share/memory/metaspaceShared.cpp index c3e4355112d..dc9a2681561 100644 --- a/src/hotspot/share/memory/metaspaceShared.cpp +++ b/src/hotspot/share/memory/metaspaceShared.cpp @@ -817,10 +817,11 @@ class CppVtableInfo { } }; +static inline intptr_t* vtable_of(Metadata* m) { + return *((intptr_t**)m); +} + template class CppVtableCloner : public T { - static intptr_t* vtable_of(Metadata& m) { - return *((intptr_t**)&m); - } static CppVtableInfo* _info; static int get_vtable_length(const char* name); @@ -841,6 +842,8 @@ template class CppVtableCloner : public T { intptr_t* vptr = *(intptr_t**)obj; return vptr == _info->cloned_vtable(); } + + static void init_orig_cpp_vtptr(int kind); }; template CppVtableInfo* CppVtableCloner::_info = NULL; @@ -866,7 +869,7 @@ intptr_t* CppVtableCloner::clone_vtable(const char* name, CppVtableInfo* info } T tmp; // Allocate temporary dummy metadata object to get to the original vtable. int n = info->vtable_size(); - intptr_t* srcvtable = vtable_of(tmp); + intptr_t* srcvtable = vtable_of(&tmp); intptr_t* dstvtable = info->cloned_vtable(); // We already checked (and, if necessary, adjusted n) when the vtables were allocated, so we are @@ -912,8 +915,8 @@ int CppVtableCloner::get_vtable_length(const char* name) { CppVtableTesterA a; CppVtableTesterB b; - intptr_t* avtable = vtable_of(a); - intptr_t* bvtable = vtable_of(b); + intptr_t* avtable = vtable_of(&a); + intptr_t* bvtable = vtable_of(&b); // Start at slot 1, because slot 0 may be RTTI (on Solaris/Sparc) int vtable_len = 1; @@ -937,15 +940,32 @@ int CppVtableCloner::get_vtable_length(const char* name) { #define ZERO_CPP_VTABLE(c) \ CppVtableCloner::zero_vtable_clone(); -//------------------------------ for DynamicDumpSharedSpaces - start +#define INIT_ORIG_CPP_VTPTRS(c) \ + CppVtableCloner::init_orig_cpp_vtptr(c##_Kind); + #define DECLARE_CLONED_VTABLE_KIND(c) c ## _Kind, -enum { - // E.g., ConstantPool_Kind == 0, InstanceKlass == 1, etc. +enum ClonedVtableKind { + // E.g., ConstantPool_Kind == 0, InstanceKlass_Kind == 1, etc. CPP_VTABLE_PATCH_TYPES_DO(DECLARE_CLONED_VTABLE_KIND) _num_cloned_vtable_kinds }; +// This is a map of all the original vtptrs. E.g., for +// ConstantPool *cp = new (...) ConstantPool(...) ; // a dynamically allocated constant pool +// the following holds true: +// _orig_cpp_vtptrs[ConstantPool_Kind] == ((intptr_t**)cp)[0] +static intptr_t* _orig_cpp_vtptrs[_num_cloned_vtable_kinds]; +static bool _orig_cpp_vtptrs_inited = false; + +template +void CppVtableCloner::init_orig_cpp_vtptr(int kind) { + assert(kind < _num_cloned_vtable_kinds, "sanity"); + T tmp; // Allocate temporary dummy metadata object to get to the original vtable. + intptr_t* srcvtable = vtable_of(&tmp); + _orig_cpp_vtptrs[kind] = srcvtable; +} + // This is the index of all the cloned vtables. E.g., for // ConstantPool* cp = ....; // an archived constant pool // InstanceKlass* ik = ....;// an archived class @@ -964,7 +984,12 @@ void MetaspaceShared::serialize_cloned_cpp_vtptrs(SerializeClosure* soc) { soc->do_ptr((void**)&_cloned_cpp_vtptrs); } -intptr_t* MetaspaceShared::fix_cpp_vtable_for_dynamic_archive(MetaspaceObj::Type msotype, address obj) { +intptr_t* MetaspaceShared::get_archived_cpp_vtable(MetaspaceObj::Type msotype, address obj) { + if (!_orig_cpp_vtptrs_inited) { + CPP_VTABLE_PATCH_TYPES_DO(INIT_ORIG_CPP_VTPTRS); + _orig_cpp_vtptrs_inited = true; + } + Arguments::assert_is_dumping_archive(); int kind = -1; switch (msotype) { @@ -981,55 +1006,21 @@ intptr_t* MetaspaceShared::fix_cpp_vtable_for_dynamic_archive(MetaspaceObj::Type case MetaspaceObj::RecordComponentType: // These have no vtables. break; - case MetaspaceObj::ClassType: - { - Klass* k = (Klass*)obj; - assert(k->is_klass(), "must be"); - if (k->is_inline_klass()) { - kind = InlineKlass_Kind; - } else if (k->is_instance_klass()) { - InstanceKlass* ik = InstanceKlass::cast(k); - if (ik->is_class_loader_instance_klass()) { - kind = InstanceClassLoaderKlass_Kind; - } else if (ik->is_reference_instance_klass()) { - kind = InstanceRefKlass_Kind; - } else if (ik->is_mirror_instance_klass()) { - kind = InstanceMirrorKlass_Kind; - } else { - kind = InstanceKlass_Kind; - } - } else if (k->is_typeArray_klass()) { - kind = TypeArrayKlass_Kind; - } else { - assert(k->is_objArray_klass(), "must be"); - kind = ObjArrayKlass_Kind; - } - } - break; - - case MetaspaceObj::MethodType: - { - Method* m = (Method*)obj; - assert(m->is_method(), "must be"); - kind = Method_Kind; - } - break; - case MetaspaceObj::MethodDataType: // We don't archive MethodData <-- should have been removed in removed_unsharable_info ShouldNotReachHere(); break; - - case MetaspaceObj::ConstantPoolType: - { - ConstantPool *cp = (ConstantPool*)obj; - assert(cp->is_constantPool(), "must be"); - kind = ConstantPool_Kind; - } - break; - default: - ShouldNotReachHere(); + for (kind = 0; kind < _num_cloned_vtable_kinds; kind ++) { + if (vtable_of((Metadata*)obj) == _orig_cpp_vtptrs[kind]) { + break; + } + } + if (kind >= _num_cloned_vtable_kinds) { + fatal("Cannot find C++ vtable for " INTPTR_FORMAT " -- you probably added" + " a new subtype of Klass or MetaData without updating CPP_VTABLE_PATCH_TYPES_DO", + p2i(obj)); + } } if (kind >= 0) { @@ -1040,8 +1031,6 @@ intptr_t* MetaspaceShared::fix_cpp_vtable_for_dynamic_archive(MetaspaceObj::Type } } -//------------------------------ for DynamicDumpSharedSpaces - end - // This can be called at both dump time and run time: // - clone the contents of the c++ vtables into the space // allocated by allocate_cpp_vtable_clones() @@ -1340,9 +1329,9 @@ class ArchiveCompactor : AllStatic { } memcpy(p, obj, bytes); - intptr_t* cloned_vtable = MetaspaceShared::fix_cpp_vtable_for_dynamic_archive(ref->msotype(), (address)p); - if (cloned_vtable != NULL) { - *(address*)p = (address)cloned_vtable; + intptr_t* archived_vtable = MetaspaceShared::get_archived_cpp_vtable(ref->msotype(), (address)p); + if (archived_vtable != NULL) { + *(address*)p = (address)archived_vtable; ArchivePtrMarker::mark_pointer((address*)p); } diff --git a/src/hotspot/share/memory/metaspaceShared.hpp b/src/hotspot/share/memory/metaspaceShared.hpp index 15efa49e947..2c3b10fcd07 100644 --- a/src/hotspot/share/memory/metaspaceShared.hpp +++ b/src/hotspot/share/memory/metaspaceShared.hpp @@ -354,7 +354,7 @@ class MetaspaceShared : AllStatic { static Klass* get_relocated_klass(Klass *k, bool is_final=false); static void allocate_cloned_cpp_vtptrs(); - static intptr_t* fix_cpp_vtable_for_dynamic_archive(MetaspaceObj::Type msotype, address obj); + static intptr_t* get_archived_cpp_vtable(MetaspaceObj::Type msotype, address obj); static void initialize_ptr_marker(CHeapBitMap* ptrmap); // This is the base address as specified by -XX:SharedBaseAddress during -Xshare:dump. diff --git a/src/hotspot/share/oops/inlineKlass.cpp b/src/hotspot/share/oops/inlineKlass.cpp index b579144218e..7b47af18283 100644 --- a/src/hotspot/share/oops/inlineKlass.cpp +++ b/src/hotspot/share/oops/inlineKlass.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "code/codeCache.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/collectedHeap.inline.hpp" #include "gc/shared/gcLocker.inline.hpp" diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index dad7b73cd7b..7d4edd8c8b7 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -1291,15 +1291,23 @@ void InstanceKlass::initialize_impl(TRAPS) { // Step 9 { DTRACE_CLASSINIT_PROBE_WAIT(clinit, -1, wait); - // Timer includes any side effects of class initialization (resolution, - // etc), but not recursive entry into call_class_initializer(). - PerfClassTraceTime timer(ClassLoader::perf_class_init_time(), - ClassLoader::perf_class_init_selftime(), - ClassLoader::perf_classes_inited(), - jt->get_thread_stat()->perf_recursion_counts_addr(), - jt->get_thread_stat()->perf_timers_addr(), - PerfClassTraceTime::CLASS_CLINIT); - call_class_initializer(THREAD); + if (class_initializer() != NULL) { + // Timer includes any side effects of class initialization (resolution, + // etc), but not recursive entry into call_class_initializer(). + PerfClassTraceTime timer(ClassLoader::perf_class_init_time(), + ClassLoader::perf_class_init_selftime(), + ClassLoader::perf_classes_inited(), + jt->get_thread_stat()->perf_recursion_counts_addr(), + jt->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::CLASS_CLINIT); + call_class_initializer(THREAD); + } else { + // The elapsed time is so small it's not worth counting. + if (UsePerfData) { + ClassLoader::perf_classes_inited()->inc(); + } + call_class_initializer(THREAD); + } } // Step 10 diff --git a/src/hotspot/share/oops/symbol.cpp b/src/hotspot/share/oops/symbol.cpp index ffda659dd7e..982628bef3b 100644 --- a/src/hotspot/share/oops/symbol.cpp +++ b/src/hotspot/share/oops/symbol.cpp @@ -36,6 +36,7 @@ #include "oops/symbol.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" +#include "runtime/signature.hpp" #include "utilities/utf8.hpp" uint32_t Symbol::pack_hash_and_refcount(short hash, int refcount) { diff --git a/src/hotspot/share/opto/arraycopynode.hpp b/src/hotspot/share/opto/arraycopynode.hpp index acb87fd0e5a..7e62a96488a 100644 --- a/src/hotspot/share/opto/arraycopynode.hpp +++ b/src/hotspot/share/opto/arraycopynode.hpp @@ -114,8 +114,9 @@ class ArrayCopyNode : public CallNode { BasicType copy_type, const Type* value_type); static bool may_modify_helper(const TypeOopPtr *t_oop, Node* n, PhaseTransform *phase, CallNode*& call); - +public: static Node* load(BarrierSetC2* bs, PhaseGVN *phase, Node*& ctl, MergeMemNode* mem, Node* addr, const TypePtr* adr_type, const Type *type, BasicType bt); +private: void store(BarrierSetC2* bs, PhaseGVN *phase, Node*& ctl, MergeMemNode* mem, Node* addr, const TypePtr* adr_type, Node* val, const Type *type, BasicType bt); public: @@ -155,7 +156,7 @@ class ArrayCopyNode : public CallNode { bool is_clone_array() const { assert(_kind != None, "should bet set"); return _kind == CloneArray; } // is_clone_oop_array is used when oop arrays need GC barriers bool is_clone_oop_array() const { assert(_kind != None, "should bet set"); return _kind == CloneOopArray; } - // is_clonebasic - is true for any type of clone that doesn't need a barrier. + // is_clonebasic - is true for any type of clone that doesn't need a writebarrier. bool is_clonebasic() const { assert(_kind != None, "should bet set"); return _kind == CloneInst || _kind == CloneArray; } bool is_copyof() const { assert(_kind != None, "should bet set"); return _kind == CopyOf; } bool is_copyof_validated() const { assert(_kind != None, "should bet set"); return _kind == CopyOf && _arguments_validated; } diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp index 9cb9dc84d72..e0233bf281b 100644 --- a/src/hotspot/share/opto/c2compiler.cpp +++ b/src/hotspot/share/opto/c2compiler.cpp @@ -99,7 +99,7 @@ void C2Compiler::initialize() { } } -void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) { +void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, bool install_code, DirectiveSet* directive) { assert(is_initialized(), "Compiler thread must be initialized"); bool subsume_loads = SubsumeLoads; @@ -109,7 +109,7 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, Dir while (!env->failing()) { // Attempt to compile while subsuming loads into machine instructions. - Compile C(env, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing, directive); + Compile C(env, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing, install_code, directive); // Check result and retry if appropriate. if (C.failure_reason() != NULL) { @@ -151,7 +151,6 @@ void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, Dir continue; // retry } } - // print inlining for last compilation only C.dump_print_inlining(); diff --git a/src/hotspot/share/opto/c2compiler.hpp b/src/hotspot/share/opto/c2compiler.hpp index ba059350b51..ede9f940aa4 100644 --- a/src/hotspot/share/opto/c2compiler.hpp +++ b/src/hotspot/share/opto/c2compiler.hpp @@ -43,6 +43,7 @@ class C2Compiler : public AbstractCompiler { void compile_method(ciEnv* env, ciMethod* target, int entry_bci, + bool install_code, DirectiveSet* directive); // sentinel value used to trigger backtracking in compile_method(). diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index dfb3799b4c4..2dd4d8de5ab 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -1344,6 +1344,30 @@ Node* PhiNode::Identity(PhaseGVN* phase) { } + // Looking for phis with identical inputs. If we find one that has + // type TypePtr::BOTTOM, replace the current phi with the bottom phi. + if (phase->is_IterGVN() && type() == Type::MEMORY && adr_type() != + TypePtr::BOTTOM && !adr_type()->is_known_instance()) { + uint phi_len = req(); + Node* phi_reg = region(); + for (DUIterator_Fast imax, i = phi_reg->fast_outs(imax); i < imax; i++) { + Node* u = phi_reg->fast_out(i); + if (u->is_Phi() && u->as_Phi()->type() == Type::MEMORY && + u->adr_type() == TypePtr::BOTTOM && u->in(0) == phi_reg && + u->req() == phi_len) { + for (uint j = 1; j < phi_len; j++) { + if (in(j) != u->in(j)) { + u = NULL; + break; + } + } + if (u != NULL) { + return u; + } + } + } + } + return this; // No identity } diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index ef1e334ffc4..0e8ba7f5917 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -26,7 +26,7 @@ #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" #include "ci/ciReplay.hpp" -#include "classfile/systemDictionary.hpp" +#include "classfile/javaClasses.hpp" #include "code/exceptionHandlerTable.hpp" #include "code/nmethod.hpp" #include "compiler/compileBroker.hpp" @@ -507,12 +507,13 @@ debug_only( int Compile::_debug_idx = 100000; ) Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci, - bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing, DirectiveSet* directive) + bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing, bool install_code, DirectiveSet* directive) : Phase(Compiler), _compile_id(ci_env->compile_id()), _save_argument_registers(false), _subsume_loads(subsume_loads), _do_escape_analysis(do_escape_analysis), + _install_code(install_code), _eliminate_boxing(eliminate_boxing), _method(target), _entry_bci(osr_bci), @@ -801,6 +802,7 @@ Compile::Compile( ciEnv* ci_env, _save_argument_registers(save_arg_registers), _subsume_loads(true), _do_escape_analysis(false), + _install_code(true), _eliminate_boxing(false), _method(NULL), _entry_bci(InvocationEntryBci), diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index f00640effe1..96097889708 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -248,6 +248,7 @@ class Compile : public Phase { const bool _save_argument_registers; // save/restore arg regs for trampolines const bool _subsume_loads; // Load can be matched as part of a larger op. const bool _do_escape_analysis; // Do escape analysis. + const bool _install_code; // Install the code that was compiled const bool _eliminate_boxing; // Do boxing elimination. ciMethod* _method; // The method being compiled. int _entry_bci; // entry bci for osr methods. @@ -512,7 +513,7 @@ class Compile : public Phase { /** Do aggressive boxing elimination. */ bool aggressive_unboxing() const { return _eliminate_boxing && AggressiveUnboxing; } bool save_argument_registers() const { return _save_argument_registers; } - + bool should_install_code() const { return _install_code; } // Other fixed compilation parameters. ciMethod* method() const { return _method; } @@ -678,23 +679,20 @@ class Compile : public Phase { assert(!_macro_nodes->contains(n), "duplicate entry in expand list"); _macro_nodes->append(n); } - void remove_macro_node(Node * n) { - // this function may be called twice for a node so check - // that the node is in the array before attempting to remove it - if (_macro_nodes->contains(n)) - _macro_nodes->remove(n); + void remove_macro_node(Node* n) { + // this function may be called twice for a node so we can only remove it + // if it's still existing. + _macro_nodes->remove_if_existing(n); // remove from _predicate_opaqs list also if it is there - if (predicate_count() > 0 && _predicate_opaqs->contains(n)){ - _predicate_opaqs->remove(n); + if (predicate_count() > 0) { + _predicate_opaqs->remove_if_existing(n); } } - void add_expensive_node(Node * n); - void remove_expensive_node(Node * n) { - if (_expensive_nodes->contains(n)) { - _expensive_nodes->remove(n); - } + void add_expensive_node(Node* n); + void remove_expensive_node(Node* n) { + _expensive_nodes->remove_if_existing(n); } - void add_predicate_opaq(Node * n) { + void add_predicate_opaq(Node* n) { assert(!_predicate_opaqs->contains(n), "duplicate entry in predicate opaque1"); assert(_macro_nodes->contains(n), "should have already been in macro list"); _predicate_opaqs->append(n); @@ -703,9 +701,7 @@ class Compile : public Phase { // Range check dependent CastII nodes that can be removed after loop optimizations void add_range_check_cast(Node* n); void remove_range_check_cast(Node* n) { - if (_range_check_casts->contains(n)) { - _range_check_casts->remove(n); - } + _range_check_casts->remove_if_existing(n); } Node* range_check_cast_node(int idx) const { return _range_check_casts->at(idx); } int range_check_cast_count() const { return _range_check_casts->length(); } @@ -714,9 +710,7 @@ class Compile : public Phase { void add_opaque4_node(Node* n); void remove_opaque4_node(Node* n) { - if (_opaque4_nodes->contains(n)) { - _opaque4_nodes->remove(n); - } + _opaque4_nodes->remove_if_existing(n); } Node* opaque4_node(int idx) const { return _opaque4_nodes->at(idx); } int opaque4_count() const { return _opaque4_nodes->length(); } @@ -1027,7 +1021,7 @@ class Compile : public Phase { // continuation. Compile(ciEnv* ci_env, ciMethod* target, int entry_bci, bool subsume_loads, bool do_escape_analysis, - bool eliminate_boxing, DirectiveSet* directive); + bool eliminate_boxing, bool install_code, DirectiveSet* directive); // Second major entry point. From the TypeFunc signature, generate code // to pass arguments from the Java calling convention to the C calling diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 8ce9797db43..6a11d3f2197 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -26,6 +26,7 @@ #include "ci/ciFlatArrayKlass.hpp" #include "ci/ciInlineKlass.hpp" #include "ci/ciUtilities.hpp" +#include "classfile/javaClasses.hpp" #include "compiler/compileLog.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/c2/barrierSetC2.hpp" diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index 6fee45f0651..23c34d23e7f 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -319,7 +319,9 @@ Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, Node* base = ac->in(ArrayCopyNode::Src); Node* adr = _igvn.transform(new AddPNode(base, base, MakeConX(offset))); const TypePtr* adr_type = _igvn.type(base)->is_ptr()->add_offset(offset); - res = LoadNode::make(_igvn, ctl, mem, adr, adr_type, type, bt, MemNode::unordered, LoadNode::UnknownControl); + MergeMemNode* mergemen = MergeMemNode::make(mem); + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + res = ArrayCopyNode::load(bs, &_igvn, ctl, mergemen, adr, adr_type, type, bt); } else { if (ac->modifies(offset, offset, &_igvn, true)) { assert(ac->in(ArrayCopyNode::Dest) == alloc->result_cast(), "arraycopy destination should be allocation's result"); @@ -362,11 +364,12 @@ Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset, adr_type = adr_type->is_aryptr()->add_field_offset_and_offset(offset)->add_offset(Type::OffsetBot); adr = _igvn.transform(new CastPPNode(adr, adr_type)); } - res = LoadNode::make(_igvn, ctl, mem, adr, adr_type, type, bt, MemNode::unordered, LoadNode::UnknownControl); + MergeMemNode* mergemen = MergeMemNode::make(mem); + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + res = ArrayCopyNode::load(bs, &_igvn, ctl, mergemen, adr, adr_type, type, bt); } } if (res != NULL) { - res = _igvn.transform(res); if (ftype->isa_narrowoop()) { // PhaseMacroExpand::scalar_replacement adds DecodeN nodes assert(res->isa_DecodeN(), "should be narrow oop"); diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 946d80777e2..445bdc40c1b 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "ci/ciFlatArrayKlass.hpp" +#include "classfile/javaClasses.hpp" #include "classfile/systemDictionary.hpp" #include "compiler/compileLog.hpp" #include "gc/shared/barrierSet.hpp" @@ -534,11 +535,24 @@ bool MemNode::detect_ptr_independence(Node* p1, AllocateNode* a1, Node* LoadNode::find_previous_arraycopy(PhaseTransform* phase, Node* ld_alloc, Node*& mem, bool can_see_stored_value) const { if (mem->is_Proj() && mem->in(0) != NULL && (mem->in(0)->Opcode() == Op_MemBarStoreStore || mem->in(0)->Opcode() == Op_MemBarCPUOrder)) { - Node* mb = mem->in(0); - if (mb->in(0) != NULL && mb->in(0)->is_Proj() && - mb->in(0)->in(0) != NULL && mb->in(0)->in(0)->is_ArrayCopy()) { - ArrayCopyNode* ac = mb->in(0)->in(0)->as_ArrayCopy(); - if (ac->is_clonebasic()) { + if (ld_alloc != NULL) { + // Check if there is an array copy for a clone + Node* mb = mem->in(0); + ArrayCopyNode* ac = NULL; + if (mb->in(0) != NULL && mb->in(0)->is_Proj() && + mb->in(0)->in(0) != NULL && mb->in(0)->in(0)->is_ArrayCopy()) { + ac = mb->in(0)->in(0)->as_ArrayCopy(); + } else { + // Step over GC barrier when ReduceInitialCardMarks is disabled + BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); + Node* control_proj_ac = bs->step_over_gc_barrier(mb->in(0)); + + if (control_proj_ac->is_Proj() && control_proj_ac->in(0)->is_ArrayCopy()) { + ac = control_proj_ac->in(0)->as_ArrayCopy(); + } + } + + if (ac != NULL && ac->is_clonebasic()) { AllocateNode* alloc = AllocateNode::Ideal_allocation(ac->in(ArrayCopyNode::Dest), phase); if (alloc != NULL && alloc == ld_alloc) { return ac; @@ -4717,24 +4731,6 @@ Node *MergeMemNode::Ideal(PhaseGVN *phase, bool can_reshape) { } // else preceding memory was not a MergeMem - // replace equivalent phis (unfortunately, they do not GVN together) - if (new_mem != NULL && new_mem != new_base && - new_mem->req() == phi_len && new_mem->in(0) == phi_reg) { - if (new_mem->is_Phi()) { - PhiNode* phi_mem = new_mem->as_Phi(); - for (uint i = 1; i < phi_len; i++) { - if (phi_base->in(i) != phi_mem->in(i)) { - phi_mem = NULL; - break; - } - } - if (phi_mem != NULL) { - // equivalent phi nodes; revert to the def - new_mem = new_base; - } - } - } - // maybe store down a new value Node* new_in = new_mem; if (new_in == new_base) new_in = empty_mem; diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp index 86de170f37e..3a6ca8da4e8 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -3332,7 +3332,9 @@ uint PhaseOutput::scratch_emit_size(const Node* n) { } void PhaseOutput::install() { - if (C->stub_function() != NULL) { + if (!C->should_install_code()) { + return; + } else if (C->stub_function() != NULL) { install_stub(C->stub_name(), C->save_argument_registers()); } else { diff --git a/src/hotspot/share/opto/stringopts.cpp b/src/hotspot/share/opto/stringopts.cpp index 084818e833e..3352a387afa 100644 --- a/src/hotspot/share/opto/stringopts.cpp +++ b/src/hotspot/share/opto/stringopts.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/javaClasses.hpp" #include "compiler/compileLog.hpp" #include "opto/addnode.hpp" #include "opto/callGenerator.hpp" diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 089d630e8e2..6e4d2277be0 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -755,6 +755,13 @@ Node* CmpLNode::Ideal(PhaseGVN* phase, bool can_reshape) { // Degraded to a simple null check, use old acmp return new CmpPNode(a, b); } + const TypeLong *t2 = phase->type(in(2))->isa_long(); + if (Opcode() == Op_CmpL && in(1)->Opcode() == Op_ConvI2L && t2 && t2->is_con()) { + const jlong con = t2->get_con(); + if (con >= min_jint && con <= max_jint) { + return new CmpINode(in(1)->in(1), phase->intcon((jint)con)); + } + } return NULL; } diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 3ec0dc34add..342773ebf61 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -28,8 +28,8 @@ #include "ci/ciInlineKlass.hpp" #include "ci/ciMethodData.hpp" #include "ci/ciTypeFlow.hpp" +#include "classfile/javaClasses.hpp" #include "classfile/symbolTable.hpp" -#include "classfile/systemDictionary.hpp" #include "compiler/compileLog.hpp" #include "libadt/dict.hpp" #include "memory/oopFactory.hpp" diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 4aa584491cf..ac70e51be4b 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -96,9 +96,11 @@ #if INCLUDE_CDS #include "classfile/systemDictionaryShared.hpp" #endif +#if INCLUDE_JFR +#include "jfr/jfr.hpp" +#endif #include -#include /* NOTE about use of any ctor or function call that can trigger a safepoint/GC: @@ -3148,7 +3150,7 @@ JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread)) } #if INCLUDE_JFR - if (JfrRecorder::is_recording() && EventThreadStart::is_enabled() && + if (Jfr::is_recording() && EventThreadStart::is_enabled() && EventThreadStart::is_stacktrace_enabled()) { JfrThreadLocal* tl = native_thread->jfr_thread_local(); // skip Thread.start() and Thread.start0() diff --git a/src/hotspot/share/prims/jvmtiRawMonitor.hpp b/src/hotspot/share/prims/jvmtiRawMonitor.hpp index dbf6bca9a09..c7089a59198 100644 --- a/src/hotspot/share/prims/jvmtiRawMonitor.hpp +++ b/src/hotspot/share/prims/jvmtiRawMonitor.hpp @@ -137,12 +137,7 @@ class JvmtiPendingMonitors : public AllStatic { // Return false if monitor is not found in the list. static bool exit(JvmtiRawMonitor* monitor) { - if (monitors()->contains(monitor)) { - monitors()->remove(monitor); - return true; - } else { - return false; - } + return monitors()->remove_if_existing(monitor); } static void transition_raw_monitors(); diff --git a/src/hotspot/share/prims/methodHandles.hpp b/src/hotspot/share/prims/methodHandles.hpp index cd57f2146a0..e5c818d5ea6 100644 --- a/src/hotspot/share/prims/methodHandles.hpp +++ b/src/hotspot/share/prims/methodHandles.hpp @@ -25,7 +25,7 @@ #ifndef SHARE_PRIMS_METHODHANDLES_HPP #define SHARE_PRIMS_METHODHANDLES_HPP -#include "classfile/javaClasses.hpp" +#include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "runtime/frame.hpp" #include "runtime/globals.hpp" diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 39854f240c8..e36f5c345fa 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -538,6 +538,10 @@ const size_t minimumSymbolTableSize = 1024; product(bool, PrintCompilation, false, \ "Print compilations") \ \ + diagnostic(intx, RepeatCompilation, 0, \ + "Repeat compilation without installing code (number of times)") \ + range(0, max_jint) \ + \ product(bool, PrintExtendedThreadInfo, false, \ "Print more information in thread dump") \ \ diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index a68b8f64956..ff7fb366e6f 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -431,7 +431,9 @@ void before_exit(JavaThread* thread) { } #if INCLUDE_JVMCI - JVMCI::shutdown(); + if (EnableJVMCI) { + JVMCI::shutdown(); + } #endif // Hang forever on exit if we're reporting an error. diff --git a/src/hotspot/share/runtime/notificationThread.cpp b/src/hotspot/share/runtime/notificationThread.cpp index fb13c03292e..7b996b1aa29 100644 --- a/src/hotspot/share/runtime/notificationThread.cpp +++ b/src/hotspot/share/runtime/notificationThread.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/javaClasses.hpp" #include "memory/universe.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/javaCalls.hpp" diff --git a/src/hotspot/share/runtime/serviceThread.cpp b/src/hotspot/share/runtime/serviceThread.cpp index f273af6aaf1..a0c9b40baba 100644 --- a/src/hotspot/share/runtime/serviceThread.cpp +++ b/src/hotspot/share/runtime/serviceThread.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/javaClasses.hpp" #include "classfile/protectionDomainCache.hpp" #include "classfile/stringTable.hpp" #include "classfile/symbolTable.hpp" diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index d565e251f1b..8682318f7c2 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -2047,7 +2047,6 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { CLEAR_PENDING_EXCEPTION; } } - JFR_ONLY(Jfr::on_java_thread_dismantle(this);) // Call Thread.exit(). We try 3 times in case we got another Thread.stop during // the execution of the method. If that is not enough, then we don't really care. Thread.stop diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index a5d0e0e155e..9c122976a99 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -26,7 +26,6 @@ #define SHARE_RUNTIME_THREAD_HPP #include "jni.h" -#include "code/compiledMethod.hpp" #include "gc/shared/gcThreadLocalData.hpp" #include "gc/shared/threadLocalAllocBuffer.hpp" #include "memory/allocation.hpp" @@ -68,6 +67,7 @@ class ParkEvent; class Parker; class MonitorInfo; +class AbstractCompiler; class ciEnv; class CompileThread; class CompileLog; diff --git a/src/hotspot/share/runtime/vmOperations.hpp b/src/hotspot/share/runtime/vmOperations.hpp index f5cc475f174..9c80558b6ea 100644 --- a/src/hotspot/share/runtime/vmOperations.hpp +++ b/src/hotspot/share/runtime/vmOperations.hpp @@ -25,12 +25,10 @@ #ifndef SHARE_RUNTIME_VMOPERATIONS_HPP #define SHARE_RUNTIME_VMOPERATIONS_HPP -#include "classfile/javaClasses.hpp" #include "memory/allocation.hpp" #include "oops/oop.hpp" #include "runtime/thread.hpp" #include "runtime/threadSMR.hpp" -#include "code/codeCache.hpp" // The following classes are used for operations // initiated by a Java thread but that must diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index 88eef76f90a..564dcf029a1 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -26,6 +26,7 @@ #include "jvm.h" #include "classfile/classLoaderHierarchyDCmd.hpp" #include "classfile/classLoaderStats.hpp" +#include "code/codeCache.hpp" #include "compiler/compileBroker.hpp" #include "compiler/directivesParser.hpp" #include "gc/shared/gcVMOperations.hpp" diff --git a/src/hotspot/share/services/threadIdTable.cpp b/src/hotspot/share/services/threadIdTable.cpp index 0d5a4f3acb4..4bc918122b2 100644 --- a/src/hotspot/share/services/threadIdTable.cpp +++ b/src/hotspot/share/services/threadIdTable.cpp @@ -1,6 +1,6 @@ /* -* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ */ #include "precompiled.hpp" +#include "classfile/javaClasses.hpp" #include "runtime/atomic.hpp" #include "runtime/interfaceSupport.inline.hpp" #include "runtime/thread.hpp" diff --git a/src/hotspot/share/utilities/growableArray.hpp b/src/hotspot/share/utilities/growableArray.hpp index 723a2263fe5..6616d7e134f 100644 --- a/src/hotspot/share/utilities/growableArray.hpp +++ b/src/hotspot/share/utilities/growableArray.hpp @@ -209,21 +209,31 @@ class GrowableArrayView : public GrowableArrayBase { return -1; } + // Order preserving remove operations. + void remove(const E& elem) { + // Assuming that element does exist. + bool removed = remove_if_existing(elem); + if (removed) return; + ShouldNotReachHere(); + } + + bool remove_if_existing(const E& elem) { + // Returns TRUE if elem is removed. for (int i = 0; i < _len; i++) { if (_data[i] == elem) { - for (int j = i + 1; j < _len; j++) _data[j-1] = _data[j]; - _len--; - return; + remove_at(i); + return true; } } - ShouldNotReachHere(); + return false; } - // The order is preserved. void remove_at(int index) { assert(0 <= index && index < _len, "illegal index"); - for (int j = index + 1; j < _len; j++) _data[j-1] = _data[j]; + for (int j = index + 1; j < _len; j++) { + _data[j-1] = _data[j]; + } _len--; } diff --git a/src/java.base/share/classes/java/net/NetworkInterface.java b/src/java.base/share/classes/java/net/NetworkInterface.java index b5351b5f4e7..1668ddbf347 100644 --- a/src/java.base/share/classes/java/net/NetworkInterface.java +++ b/src/java.base/share/classes/java/net/NetworkInterface.java @@ -576,7 +576,13 @@ public boolean isVirtual() { * as this object. *

* Two instances of {@code NetworkInterface} represent the same - * NetworkInterface if both name and addrs are the same for both. + * NetworkInterface if both the name and the set of {@code InetAddress}es + * bound to the interfaces are equal. + * + * @apiNote two {@code NetworkInterface} objects referring to the same + * underlying interface may not compare equal if the addresses + * of the underlying interface are being dynamically updated by + * the system. * * @param obj the object to compare against. * @return {@code true} if the objects are the same; diff --git a/src/java.base/share/classes/java/security/Provider.java b/src/java.base/share/classes/java/security/Provider.java index 6a7512018e8..d23f6cb6096 100644 --- a/src/java.base/share/classes/java/security/Provider.java +++ b/src/java.base/share/classes/java/security/Provider.java @@ -868,7 +868,7 @@ private void check(String directive) { // For backward compatibility, the registration ordering of // SecureRandom (RNG) algorithms needs to be preserved for // "new SecureRandom()" calls when this provider is used - private transient Set prngServices; + private transient Set prngAlgos; // Map // used for services added via legacy methods, init on demand @@ -1089,7 +1089,7 @@ private void implClear() { legacyChanged = false; servicesChanged = false; serviceSet = null; - prngServices = null; + prngAlgos = null; super.clear(); putId(); } @@ -1221,7 +1221,7 @@ private void parseLegacyPut(String name, String value) { s.className = className; if (type.equals("SecureRandom")) { - updateSecureRandomEntries(true, s); + updateSecureRandomEntries(true, s.algorithm); } } else { // attribute // e.g. put("MessageDigest.SHA-1 ImplementedIn", "Software"); @@ -1383,25 +1383,25 @@ protected void putService(Service s) { synchronized (this) { putPropertyStrings(s); if (type.equals("SecureRandom")) { - updateSecureRandomEntries(true, s); + updateSecureRandomEntries(true, s.algorithm); } } } - private void updateSecureRandomEntries(boolean doAdd, Service s) { + // keep tracks of the registered secure random algos and store them in order + private void updateSecureRandomEntries(boolean doAdd, String s) { Objects.requireNonNull(s); if (doAdd) { - if (prngServices == null) { - prngServices = new LinkedHashSet(); + if (prngAlgos == null) { + prngAlgos = new LinkedHashSet(); } - prngServices.add(s); + prngAlgos.add(s); } else { - prngServices.remove(s); + prngAlgos.remove(s); } if (debug != null) { - debug.println((doAdd? "Add":"Remove") + " SecureRandom algo " + - s.getAlgorithm()); + debug.println((doAdd? "Add":"Remove") + " SecureRandom algo " + s); } } @@ -1411,12 +1411,15 @@ synchronized Service getDefaultSecureRandomService() { checkInitialized(); if (legacyChanged) { - prngServices = null; + prngAlgos = null; ensureLegacyParsed(); } - if (prngServices != null && !prngServices.isEmpty()) { - return prngServices.iterator().next(); + if (prngAlgos != null && !prngAlgos.isEmpty()) { + // IMPORTANT: use the Service obj returned by getService(...) call + // as providers may override putService(...)/getService(...) and + // return their own Service objects + return getService("SecureRandom", prngAlgos.iterator().next()); } return null; @@ -1516,7 +1519,7 @@ private void implRemoveService(Service s) { synchronized (this) { removePropertyStrings(s); if (type.equals("SecureRandom")) { - updateSecureRandomEntries(false, s); + updateSecureRandomEntries(false, s.algorithm); } } } diff --git a/src/java.base/share/classes/java/util/zip/ZipEntry.java b/src/java.base/share/classes/java/util/zip/ZipEntry.java index 259391b3b43..1639eec9aed 100644 --- a/src/java.base/share/classes/java/util/zip/ZipEntry.java +++ b/src/java.base/share/classes/java/util/zip/ZipEntry.java @@ -57,7 +57,7 @@ public class ZipEntry implements ZipConstants, Cloneable { int flag = 0; // general purpose flag byte[] extra; // optional extra field data for entry String comment; // optional comment string for entry - + int posixPerms = -1;// posix permissions /** * Compression method for uncompressed entries. */ @@ -131,6 +131,7 @@ public ZipEntry(ZipEntry e) { flag = e.flag; extra = e.extra; comment = e.comment; + posixPerms = e.posixPerms; } /** diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java index 8d426f2f854..a7060353b99 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -657,6 +657,11 @@ private ZipEntry getZipEntry(String name, int pos) { e.size = CENLEN(cen, pos); e.csize = CENSIZ(cen, pos); e.method = CENHOW(cen, pos); + if (CENVEM_FA(cen, pos) == FILE_ATTRIBUTES_UNIX) { + // 12 bits for setuid, setgid, sticky + perms + e.posixPerms = CENATX_PERMS(cen, pos) & 0xFFF; + } + if (elen != 0) { int start = pos + CENHDR + nlen; e.setExtra0(Arrays.copyOfRange(cen, start, start + elen), true, false); @@ -1092,6 +1097,16 @@ public Stream stream(ZipFile zip) { public Stream entryNameStream(ZipFile zip) { return zip.entryNameStream(); } + // only set posix perms value via ZipEntry contructor for now + @Override + public int getPosixPerms(ZipEntry ze) { + return ze.posixPerms; + } + @Override + public void setPosixPerms(ZipEntry ze, int perms) { + ze.posixPerms = perms; + } + } ); isWindows = VM.getSavedProperty("os.name").contains("Windows"); diff --git a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java index 03672e590ad..47c38d9cfb6 100644 --- a/src/java.base/share/classes/java/util/zip/ZipOutputStream.java +++ b/src/java.base/share/classes/java/util/zip/ZipOutputStream.java @@ -506,6 +506,15 @@ private void writeEXT(ZipEntry e) throws IOException { } } + /** + * Adds information about compatibility of file attribute information + * to a version value. + */ + private int versionMadeBy(ZipEntry e, int version) { + return (e.posixPerms < 0) ? version : + VERSION_MADE_BY_BASE_UNIX | (version & 0xff); + } + /* * Write central directory (CEN) header for specified entry. * REMIND: add support for file attributes @@ -537,10 +546,10 @@ private void writeCEN(XEntry xentry) throws IOException { } writeInt(CENSIG); // CEN header signature if (hasZip64) { - writeShort(45); // ver 4.5 for zip64 + writeShort(versionMadeBy(e,45)); // ver 4.5 for zip64 writeShort(45); } else { - writeShort(version); // version made by + writeShort(versionMadeBy(e, version)); // version made by writeShort(version); // version needed to extract } writeShort(flag); // general purpose bit flag @@ -597,7 +606,8 @@ private void writeCEN(XEntry xentry) throws IOException { } writeShort(0); // starting disk number writeShort(0); // internal file attributes (unused) - writeInt(0); // external file attributes (unused) + // external file attributes, used for storing posix permissions + writeInt(e.posixPerms > 0 ? e.posixPerms << 16 : 0); writeInt(offset); // relative offset of local header writeBytes(nameBytes, 0, nameBytes.length); diff --git a/src/java.base/share/classes/java/util/zip/ZipUtils.java b/src/java.base/share/classes/java/util/zip/ZipUtils.java index 60c251aced5..b33d8b31d8c 100644 --- a/src/java.base/share/classes/java/util/zip/ZipUtils.java +++ b/src/java.base/share/classes/java/util/zip/ZipUtils.java @@ -215,6 +215,17 @@ static final long GETSIG(byte[] b) { return LG(b, 0); } + /* + * File attribute compatibility types of CEN field "version made by" + */ + static final int FILE_ATTRIBUTES_UNIX = 3; // Unix + + /* + * Base values for CEN field "version made by" + */ + static final int VERSION_MADE_BY_BASE_UNIX = FILE_ATTRIBUTES_UNIX << 8; // Unix + + // local file (LOC) header fields static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature static final int LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract @@ -250,6 +261,7 @@ static final long GETSIG(byte[] b) { // central directory header (CEN) fields static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); } static final int CENVEM(byte[] b, int pos) { return SH(b, pos + 4); } + static final int CENVEM_FA(byte[] b, int pos) { return CH(b, pos + 5); } // file attribute compatibility static final int CENVER(byte[] b, int pos) { return SH(b, pos + 6); } static final int CENFLG(byte[] b, int pos) { return SH(b, pos + 8); } static final int CENHOW(byte[] b, int pos) { return SH(b, pos + 10);} @@ -263,6 +275,7 @@ static final long GETSIG(byte[] b) { static final int CENDSK(byte[] b, int pos) { return SH(b, pos + 34);} static final int CENATT(byte[] b, int pos) { return SH(b, pos + 36);} static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);} + static final int CENATX_PERMS(byte[] b, int pos) { return SH(b, pos + 40);} // posix permission data static final long CENOFF(byte[] b, int pos) { return LG(b, pos + 42);} // The END header is followed by a variable length comment of size < 64k. diff --git a/src/java.base/share/classes/jdk/internal/access/JavaUtilZipFileAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaUtilZipFileAccess.java index 2011b16206f..2c2f0b8f8cd 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaUtilZipFileAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaUtilZipFileAccess.java @@ -30,6 +30,7 @@ import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Stream; +import java.util.zip.ZipEntry; import java.util.zip.ZipFile; public interface JavaUtilZipFileAccess { @@ -40,5 +41,7 @@ public interface JavaUtilZipFileAccess { public Enumeration entries(ZipFile zip); public Stream stream(ZipFile zip); public Stream entryNameStream(ZipFile zip); + public void setPosixPerms(ZipEntry ze, int posixPerms); + public int getPosixPerms(ZipEntry ze); } diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index b3abc2f42ad..19e8d9c0f93 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -148,6 +148,7 @@ java.management, java.naming, java.rmi, + jdk.jartool, jdk.jlink, jdk.net, jdk.incubator.foreign; diff --git a/src/java.base/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java b/src/java.base/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java index 3fe104c6ff9..ee8b5c74ae9 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java @@ -248,7 +248,7 @@ private static X509CRL getCRL(URIName name) throws CertStoreException { debug.println("Trying to fetch CRL from DP " + uri); } - Event.report("event.crl.check", uri.toString()); + Event.report(Event.ReporterCategory.CRLCHECK, "event.crl.check", uri.toString()); CertStore ucs = null; try { ucs = URICertStore.getInstance(new URICertStoreParameters(uri)); diff --git a/src/java.base/share/classes/sun/security/provider/certpath/OCSP.java b/src/java.base/share/classes/sun/security/provider/certpath/OCSP.java index 1b9e8f9dea8..d588c1a3fe9 100644 --- a/src/java.base/share/classes/sun/security/provider/certpath/OCSP.java +++ b/src/java.base/share/classes/sun/security/provider/certpath/OCSP.java @@ -234,7 +234,7 @@ public static byte[] getOCSPBytes(List certIds, URI responderURI, debug.println("connecting to OCSP service at: " + url); } - Event.report("event.ocsp.check", url.toString()); + Event.report(Event.ReporterCategory.CRLCHECK, "event.ocsp.check", url.toString()); HttpURLConnection con = (HttpURLConnection)url.openConnection(); con.setConnectTimeout(CONNECT_TIMEOUT); con.setReadTimeout(CONNECT_TIMEOUT); diff --git a/src/java.base/share/classes/sun/security/util/Event.java b/src/java.base/share/classes/sun/security/util/Event.java index 70b0d88d215..82ed0d028cb 100644 --- a/src/java.base/share/classes/sun/security/util/Event.java +++ b/src/java.base/share/classes/sun/security/util/Event.java @@ -35,21 +35,27 @@ public final class Event { private Event() {} + public enum ReporterCategory { + CRLCHECK(), + POSIXPERMS(); + + private Reporter reporter; + } + public interface Reporter { public void handle(String type, Object... args); } - private static Reporter reporter; - public static void setReportListener(Reporter re) { - reporter = re; + public static void setReportListener(ReporterCategory cat, Reporter re) { + cat.reporter = re; } - public static void clearReportListener() { - reporter = null; + public static void clearReportListener(ReporterCategory cat) { + cat.reporter = null; } - public static void report(String type, Object... args) { - Reporter currentReporter = reporter; + public static void report(ReporterCategory cat, String type, Object... args) { + Reporter currentReporter = cat.reporter; if (currentReporter != null) { currentReporter.handle(type, args); diff --git a/src/java.base/windows/native/common/version.rc b/src/java.base/windows/native/common/version.rc index 179c220830e..1763a11ed7b 100644 --- a/src/java.base/windows/native/common/version.rc +++ b/src/java.base/windows/native/common/version.rc @@ -1,5 +1,5 @@ // -// Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -23,38 +23,43 @@ // questions. // -#include "windows.h" +#include // Need 2 defines so macro argument to XSTR will get expanded before quoting. #define XSTR(x) STR(x) #define STR(x) #x -LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US ///////////////////////////////////////////////////////////////////////////// // // Version // +#ifndef JDK_FILEOS +#define JDK_FILEOS VOS__WINDOWS32 +#endif + VS_VERSION_INFO VERSIONINFO FILEVERSION JDK_FVER PRODUCTVERSION JDK_FVER - FILEFLAGSMASK 0x3fL + FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE #ifdef _DEBUG - FILEFLAGS 0x1L + FILEFLAGS VS_FF_DEBUG #else FILEFLAGS 0x0L #endif - // FILEOS 0x4 is Win32, 0x40004 is Win32 NT only - FILEOS 0x4L - // FILETYPE should be 0x1 for .exe and 0x2 for .dll + FILEOS JDK_FILEOS FILETYPE JDK_FTYPE FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN - BLOCK "000004b0" + BLOCK "040904b0" BEGIN +#ifdef JDK_COMMENTS + VALUE "Comments", XSTR(JDK_COMMENTS) "\0" +#endif VALUE "CompanyName", XSTR(JDK_COMPANY) "\0" VALUE "FileDescription", XSTR(JDK_FILEDESC) "\0" VALUE "FileVersion", XSTR(JDK_VER) "\0" @@ -68,6 +73,6 @@ BEGIN END BLOCK "VarFileInfo" BEGIN - VALUE "Translation", 0x0, 1200 + VALUE "Translation", 0x409, 1200 END END diff --git a/src/java.desktop/share/classes/java/awt/Desktop.java b/src/java.desktop/share/classes/java/awt/Desktop.java index 6a1541548d2..3e5be31b1d5 100644 --- a/src/java.desktop/share/classes/java/awt/Desktop.java +++ b/src/java.desktop/share/classes/java/awt/Desktop.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -458,7 +458,9 @@ public void edit(File file) throws IOException { checkActionSupport(Action.EDIT); file.canWrite(); checkFileValidation(file); - + if (file.isDirectory()) { + throw new IOException(file.getPath() + " is a directory"); + } peer.edit(file); } @@ -491,7 +493,9 @@ public void print(File file) throws IOException { } checkActionSupport(Action.PRINT); checkFileValidation(file); - + if (file.isDirectory()) { + throw new IOException(file.getPath() + " is a directory"); + } peer.print(file); } diff --git a/src/java.desktop/share/classes/java/awt/image/RescaleOp.java b/src/java.desktop/share/classes/java/awt/image/RescaleOp.java index ba9307c7c06..d93410f9e0c 100644 --- a/src/java.desktop/share/classes/java/awt/image/RescaleOp.java +++ b/src/java.desktop/share/classes/java/awt/image/RescaleOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,9 @@ package java.awt.image; -import java.awt.color.ColorSpace; import java.awt.geom.Rectangle2D; import java.awt.AlphaComposite; import java.awt.Graphics2D; -import java.awt.Rectangle; import java.awt.geom.Point2D; import java.awt.RenderingHints; import sun.awt.image.ImagingLib; @@ -379,7 +377,7 @@ public final BufferedImage filter (BufferedImage src, BufferedImage dst) { { throw new IllegalArgumentException("Number of scaling constants "+ "does not equal the number of"+ - " of color or color/alpha "+ + " color or color/alpha"+ " components"); } @@ -512,7 +510,7 @@ else if (numBands != dst.getNumBands()) { if (sCheck && scaleConst != 1 && scaleConst != src.getNumBands()) { throw new IllegalArgumentException("Number of scaling constants "+ "does not equal the number of"+ - " of bands in the src raster"); + " bands in the src raster"); } // diff --git a/src/java.desktop/share/classes/javax/swing/PopupFactory.java b/src/java.desktop/share/classes/javax/swing/PopupFactory.java index bedff4d7fc2..52b86ad6ff6 100644 --- a/src/java.desktop/share/classes/javax/swing/PopupFactory.java +++ b/src/java.desktop/share/classes/javax/swing/PopupFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,18 @@ package javax.swing; -import sun.awt.EmbeddedFrame; -import sun.awt.OSInfo; -import sun.swing.SwingAccessor; - import java.applet.Applet; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.Window; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.security.AccessController; @@ -38,6 +44,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; + +import sun.awt.EmbeddedFrame; +import sun.awt.OSInfo; +import sun.swing.SwingAccessor; + import static javax.swing.ClientPropertyKey.PopupFactory_FORCE_HEAVYWEIGHT_POPUP; /** @@ -826,13 +837,12 @@ public void show() { } else { parent.add(component); } + pack(); + component.setVisible(true); } Component createComponent(Component owner) { - JComponent component = new JPanel(new BorderLayout(), true); - - component.setOpaque(true); - return component; + return new JPanel(new BorderLayout(), true); } // @@ -847,11 +857,10 @@ void reset(Component owner, Component contents, int ownerX, super.reset(owner, contents, ownerX, ownerY); JComponent component = (JComponent)getComponent(); - - component.setOpaque(contents.isOpaque()); + component.setVisible(false); component.setLocation(ownerX, ownerY); + component.setOpaque(contents.isOpaque()); component.add(contents, BorderLayout.CENTER); - contents.invalidate(); pack(); } } @@ -960,27 +969,22 @@ public void show() { (parent!=null)) { parent = parent.getParent(); } - // Set the visibility to false before adding to workaround a - // bug in Solaris in which the Popup gets added at the wrong - // location, which will result in a mouseExit, which will then - // result in the ToolTip being removed. + if (parent instanceof RootPaneContainer) { - parent = ((RootPaneContainer)parent).getLayeredPane(); - Point p = SwingUtilities.convertScreenLocationToParent(parent, - x, y); - component.setVisible(false); - component.setLocation(p.x, p.y); - parent.add(component, JLayeredPane.POPUP_LAYER, - 0); - } else { - Point p = SwingUtilities.convertScreenLocationToParent(parent, - x, y); + parent = ((RootPaneContainer) parent).getLayeredPane(); + } - component.setLocation(p.x, p.y); - component.setVisible(false); + Point p = SwingUtilities.convertScreenLocationToParent(parent, + x, y); + component.setLocation(p.x, p.y); + if (parent instanceof JLayeredPane) { + parent.add(component, JLayeredPane.POPUP_LAYER, 0); + } else { parent.add(component); } + pack(); component.setVisible(true); + component.revalidate(); } Component createComponent(Component owner) { @@ -1004,11 +1008,9 @@ void reset(Component owner, Component contents, int ownerX, super.reset(owner, contents, ownerX, ownerY); Component component = getComponent(); - + component.setVisible(false); component.setLocation(ownerX, ownerY); rootPane.getContentPane().add(contents, BorderLayout.CENTER); - contents.invalidate(); - component.validate(); pack(); } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java index bc901f7f3a2..d7f0b662faf 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java @@ -270,7 +270,7 @@ protected void installDefaults() } else if ("small".equals(scaleKey)){ scrollBarWidth *= 0.857; incrGap *= 0.857; - decrGap *= 0.714; + decrGap *= 0.857; } else if ("mini".equals(scaleKey)){ scrollBarWidth *= 0.714; incrGap *= 0.714; diff --git a/src/java.desktop/share/classes/javax/swing/text/rtf/RTFReader.java b/src/java.desktop/share/classes/javax/swing/text/rtf/RTFReader.java index 767f513e1f5..220e101354d 100644 --- a/src/java.desktop/share/classes/javax/swing/text/rtf/RTFReader.java +++ b/src/java.desktop/share/classes/javax/swing/text/rtf/RTFReader.java @@ -133,6 +133,7 @@ class RTFReader extends RTFParser static boolean useNeXTForAnsi = false; static { characterSets = new Hashtable(); + defineCharacterSet("ansicpg", latin1TranslationTable); } /* TODO: per-font font encodings ( \fcharset control word ) ? */ @@ -487,6 +488,11 @@ public boolean handleKeyword(String keyword, int parameter) keyword.equals("private")) ignoreGroupIfUnknownKeywordSave = true; + if (keyword.contains("ansicpg")) { + setCharacterSet("ansicpg"); + return true; + } + if (rtfDestination != null) { if(rtfDestination.handleKeyword(keyword, parameter)) return true; diff --git a/src/java.desktop/share/classes/sun/font/SunFontManager.java b/src/java.desktop/share/classes/sun/font/SunFontManager.java index 3145bb885d0..94552645a30 100644 --- a/src/java.desktop/share/classes/sun/font/SunFontManager.java +++ b/src/java.desktop/share/classes/sun/font/SunFontManager.java @@ -353,6 +353,9 @@ public Void run() { String[] fontInfo = getDefaultPlatformFont(); defaultFontName = fontInfo[0]; + if (defaultFontName == null && FontUtilities.debugFonts()) { + FontUtilities.getLogger().warning("defaultFontName is null"); + } defaultFontFileName = fontInfo[1]; String extraFontPath = fontConfig.getExtraFontPath(); @@ -1888,6 +1891,7 @@ private Font2D findFontFromPlatform(String lcName, int style) { * may be able to emulate the required style. */ public Font2D findFont2D(String name, int style, int fallback) { + if (name == null) return null; String lowerCaseName = name.toLowerCase(Locale.ENGLISH); String mapName = lowerCaseName + dotStyleStr(style); diff --git a/src/java.desktop/share/classes/sun/java2d/pipe/BufferedBufImgOps.java b/src/java.desktop/share/classes/sun/java2d/pipe/BufferedBufImgOps.java index 0a9cde7b181..d7dba199c76 100644 --- a/src/java.desktop/share/classes/sun/java2d/pipe/BufferedBufImgOps.java +++ b/src/java.desktop/share/classes/sun/java2d/pipe/BufferedBufImgOps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,10 +26,8 @@ package sun.java2d.pipe; import java.awt.color.ColorSpace; -import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; import java.awt.image.BufferedImageOp; -import java.awt.image.BufferedImageOp; import java.awt.image.ByteLookupTable; import java.awt.image.ColorModel; import java.awt.image.ConvolveOp; @@ -40,7 +38,6 @@ import java.awt.image.RescaleOp; import java.awt.image.ShortLookupTable; import sun.java2d.SurfaceData; -import sun.java2d.loops.CompositeType; import static sun.java2d.pipe.BufferedOpCodes.*; public class BufferedBufImgOps { @@ -137,7 +134,7 @@ public static boolean isRescaleOpValid(RescaleOp rop, { throw new IllegalArgumentException("Number of scaling constants "+ "does not equal the number of"+ - " of color or color/alpha "+ + " color or color/alpha"+ " components"); } diff --git a/src/java.desktop/unix/classes/sun/awt/FcFontManager.java b/src/java.desktop/unix/classes/sun/awt/FcFontManager.java index 7cf39dc2818..ecd7ac0ad35 100644 --- a/src/java.desktop/unix/classes/sun/awt/FcFontManager.java +++ b/src/java.desktop/unix/classes/sun/awt/FcFontManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,7 +89,8 @@ protected String[] getDefaultPlatformFont() { */ if (info[0] == null) { if (fontConfigFonts != null && fontConfigFonts.length > 0 && - fontConfigFonts[0].firstFont.fontFile != null) { + fontConfigFonts[0].firstFont.fontFile != null && + fontConfigFonts[0].firstFont.fullName != null) { info[0] = fontConfigFonts[0].firstFont.fullName; info[1] = fontConfigFonts[0].firstFont.fontFile; } else { diff --git a/src/java.desktop/windows/native/libawt/windows/awt.rc b/src/java.desktop/windows/native/libawt/windows/awt.rc index 466595178df..3bc072180d4 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt.rc +++ b/src/java.desktop/windows/native/libawt/windows/awt.rc @@ -1,5 +1,5 @@ // -// Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1997, 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,13 +23,7 @@ // questions. // -#include "windows.h" - -// Need 2 defines so macro argument to XSTR will get expanded before quoting. -#define XSTR(x) STR(x) -#define STR(x) #x - -LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#include "version.rc" AWT_ICON ICON DISCARDABLE "awt.ico" CHECK_BITMAP BITMAP DISCARDABLE "check.bmp" @@ -40,44 +34,3 @@ SECURITY_WARNING_0 ICON DISCARDABLE "security_warning_bw.ico" SECURITY_WARNING_1 ICON DISCARDABLE "security_warning_int.ico" SECURITY_WARNING_2 ICON DISCARDABLE "security_warning.ico" - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION JDK_FVER - PRODUCTVERSION JDK_FVER - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - // FILEOS 0x4 is Win32, 0x40004 is Win32 NT only - FILEOS 0x4L - // FILETYPE should be 0x1 for .exe and 0x2 for .dll - FILETYPE JDK_FTYPE - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "CompanyName", XSTR(JDK_COMPANY) "\0" - VALUE "FileDescription", XSTR(JDK_FILEDESC) "\0" - VALUE "FileVersion", XSTR(JDK_VER) "\0" - VALUE "Full Version", XSTR(JDK_VERSION_STRING) "\0" - VALUE "InternalName", XSTR(JDK_INTERNAL_NAME) "\0" - VALUE "LegalCopyright", XSTR(JDK_COPYRIGHT) "\0" - VALUE "OriginalFilename", XSTR(JDK_FNAME) "\0" - VALUE "ProductName", XSTR(JDK_NAME) "\0" - VALUE "ProductVersion", XSTR(JDK_VER) "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END diff --git a/src/java.logging/share/classes/java/util/logging/LogRecord.java b/src/java.logging/share/classes/java/util/logging/LogRecord.java index 4b88e359f7c..f99c612938e 100644 --- a/src/java.logging/share/classes/java/util/logging/LogRecord.java +++ b/src/java.logging/share/classes/java/util/logging/LogRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package java.util.logging; import java.time.Instant; import java.util.*; -import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.io.*; import java.security.AccessController; @@ -75,21 +74,6 @@ public class LogRecord implements java.io.Serializable { private static final AtomicLong globalSequenceNumber = new AtomicLong(0); - /** - * The default value of threadID will be the current thread's - * thread id, for ease of correlation, unless it is greater than - * MIN_SEQUENTIAL_THREAD_ID, in which case we try harder to keep - * our promise to keep threadIDs unique by avoiding collisions due - * to 32-bit wraparound. Unfortunately, LogRecord.getThreadID() - * returns int, while Thread.getId() returns long. - */ - private static final int MIN_SEQUENTIAL_THREAD_ID = Integer.MAX_VALUE / 2; - - private static final AtomicInteger nextThreadId - = new AtomicInteger(MIN_SEQUENTIAL_THREAD_ID); - - private static final ThreadLocal threadIds = new ThreadLocal<>(); - /** * Logging message level */ @@ -120,6 +104,11 @@ public class LogRecord implements java.io.Serializable { */ private int threadID; + /** + * long value of Thread ID for thread that issued logging call. + */ + private long longThreadID; + /** * The Throwable (if any) associated with log message */ @@ -147,7 +136,10 @@ public class LogRecord implements java.io.Serializable { * @serialField sourceClassName String Class that issued logging call * @serialField sourceMethodName String Method that issued logging call * @serialField message String Non-localized raw message text - * @serialField threadID int Thread ID for thread that issued logging call + * @serialField threadID int this is deprecated and is available for backward compatibility. + * Values may have been synthesized. If present, {@code longThreadID} represents + * the actual thread id. + * @serialField longThreadID long Thread ID for thread that issued logging call * @serialField millis long Truncated event time in milliseconds since 1970 * - calculated as getInstant().toEpochMilli(). * The event time instant can be reconstructed using @@ -164,6 +156,7 @@ public class LogRecord implements java.io.Serializable { * @serialField resourceBundleName String Resource bundle name to localized * log message */ + @Serial private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[] { new ObjectStreamField("level", Level.class), @@ -172,6 +165,7 @@ public class LogRecord implements java.io.Serializable { new ObjectStreamField("sourceMethodName", String.class), new ObjectStreamField("message", String.class), new ObjectStreamField("threadID", int.class), + new ObjectStreamField("longThreadID", long.class), new ObjectStreamField("millis", long.class), new ObjectStreamField("nanoAdjustment", int.class), new ObjectStreamField("thrown", Throwable.class), @@ -184,20 +178,22 @@ public class LogRecord implements java.io.Serializable { private transient ResourceBundle resourceBundle; /** - * Returns the default value for a new LogRecord's threadID. + * Synthesizes a pseudo unique integer value from a long {@code id} value. + * For backward compatibility with previous releases,the returned integer is + * such that for any positive long less than or equals to {@code Integer.MAX_VALUE}, + * the returned integer is equal to the original value. + * Otherwise - it is synthesized with a best effort hashing algorithm, + * and the returned value is negative. + * Calling this method multiple times with the same value always yields the same result. + * + * @return thread id */ - private int defaultThreadID() { - long tid = Thread.currentThread().getId(); - if (tid < MIN_SEQUENTIAL_THREAD_ID) { - return (int) tid; - } else { - Integer id = threadIds.get(); - if (id == null) { - id = nextThreadId.getAndIncrement(); - threadIds.set(id); - } - return id; - } + + private int shortThreadID(long id) { + if (id >= 0 && id <= Integer.MAX_VALUE) + return (int) id; + int hash = Long.hashCode(id); + return hash < 0 ? hash : (-1 - hash); } /** @@ -225,10 +221,13 @@ public LogRecord(Level level, String msg) { message = msg; // Assign a thread ID and a unique sequence number. sequenceNumber = globalSequenceNumber.getAndIncrement(); - threadID = defaultThreadID(); + long id = Thread.currentThread().getId(); + // threadID is deprecated and this value is synthesised for backward compatibility + threadID = shortThreadID(id); + longThreadID = id; instant = Instant.now(); needToInferCaller = true; - } + } /** * Get the source Logger's name. @@ -447,8 +446,12 @@ public void setParameters(Object parameters[]) { * This is a thread identifier within the Java VM and may or * may not map to any operating system ID. * + * @deprecated Values returned by this method may be synthesized, + * and may not correspond to the actual {@linkplain Thread#getId() thread id}, + * use {@link #getLongThreadID()} instead. * @return thread ID */ + @Deprecated(since = "16") public int getThreadID() { return threadID; } @@ -456,9 +459,41 @@ public int getThreadID() { /** * Set an identifier for the thread where the message originated. * @param threadID the thread ID + * + * @deprecated This method doesn't allow to pass a long {@linkplain Thread#getId() thread id}, + * use {@link #setLongThreadID(long)} instead. */ + @Deprecated(since = "16") public void setThreadID(int threadID) { this.threadID = threadID; + this.longThreadID = threadID; + } + + /** + * Get a thread identifier for the thread where message originated + * + *

+ * This is a thread identifier within the Java VM and may or + * may not map to any operating system ID. + * + * @return thread ID + * @since 16 + */ + public long getLongThreadID() { + return longThreadID; + } + + /** + * Set an identifier for the thread where the message originated. + * + * @param longThreadID the thread ID + * @return this LogRecord + * @since 16 + */ + public LogRecord setLongThreadID(long longThreadID) { + this.threadID = shortThreadID(longThreadID); + this.longThreadID = longThreadID; + return this; } /** @@ -552,6 +587,7 @@ public void setThrown(Throwable thrown) { this.thrown = thrown; } + @Serial private static final long serialVersionUID = 5372048053134512534L; /** @@ -564,6 +600,7 @@ public void setThrown(Throwable thrown) { * a null String is written. Otherwise the output of Object.toString() * is written. */ + @Serial private void writeObject(ObjectOutputStream out) throws IOException { // We have to write serialized fields first. ObjectOutputStream.PutField pf = out.putFields(); @@ -573,6 +610,7 @@ private void writeObject(ObjectOutputStream out) throws IOException { pf.put("sourceMethodName", sourceMethodName); pf.put("message", message); pf.put("threadID", threadID); + pf.put("longThreadID", longThreadID); pf.put("millis", instant.toEpochMilli()); pf.put("nanoAdjustment", instant.getNano() % 1000_000); pf.put("thrown", thrown); @@ -594,8 +632,25 @@ private void writeObject(ObjectOutputStream out) throws IOException { } } + /** + * Initializes the LogRecord from deserialized data. + *

    + *
  • If {@code longThreadID} is present in the serial form, its value + * takes precedence over {@code threadID} and a value for {@code threadID} + * is synthesized from it, such that for {@code longThreadID} values between + * {@code 0} and {@code Integer.MAX_VALUE} inclusive, {@code longThreadID} + * and {@code threadID} will have the same value. For values outside of this + * range a negative synthesized value will be deterministically derived + * from {@code longThreadID}. + *
  • Otherwise, when only {@code threadID} is + * present, {@code longThreadID} is initialized with the value of + * {@code threadID} which may be anything between {@code Integer.MIN_VALUE} + * and {Integer.MAX_VALUE}. + *
+ */ + @Serial private void readObject(ObjectInputStream in) - throws IOException, ClassNotFoundException { + throws IOException, ClassNotFoundException { // We have to read serialized fields first. ObjectInputStream.GetField gf = in.readFields(); level = (Level) gf.get("level", null); @@ -603,7 +658,14 @@ private void readObject(ObjectInputStream in) sourceClassName = (String) gf.get("sourceClassName", null); sourceMethodName = (String) gf.get("sourceMethodName", null); message = (String) gf.get("message", null); - threadID = gf.get("threadID", 0); + // If longthreadID is not present, it will be initialised with threadID value + // If longthreadID is present, threadID might have a synthesized value + int threadID = gf.get("threadID", 0); + long longThreadID = gf.get("longThreadID", (long)threadID); + if (threadID != longThreadID) + threadID = shortThreadID(longThreadID); + this.threadID = threadID; + this.longThreadID = longThreadID; long millis = gf.get("millis", 0L); int nanoOfMilli = gf.get("nanoAdjustment", 0); instant = Instant.ofEpochSecond( @@ -641,9 +703,9 @@ private void readObject(ObjectInputStream in) // use system class loader to ensure the ResourceBundle // instance is a different instance than null loader uses final ResourceBundle bundle = - ResourceBundle.getBundle(resourceBundleName, - Locale.getDefault(), - ClassLoader.getSystemClassLoader()); + ResourceBundle.getBundle(resourceBundleName, + Locale.getDefault(), + ClassLoader.getSystemClassLoader()); resourceBundle = bundle; } catch (MissingResourceException ex) { // This is not a good place to throw an exception, @@ -697,7 +759,7 @@ static final class CallerFinder implements Predicate { private static final StackWalker WALKER; static { final PrivilegedAction action = - () -> StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); + () -> StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); WALKER = AccessController.doPrivileged(action); } @@ -736,7 +798,7 @@ public boolean test(StackWalker.StackFrame t) { private boolean isLoggerImplFrame(String cname) { return (cname.equals("java.util.logging.Logger") || - cname.startsWith("sun.util.logging.PlatformLogger")); + cname.startsWith("sun.util.logging.PlatformLogger")); } } } diff --git a/src/java.logging/share/classes/java/util/logging/XMLFormatter.java b/src/java.logging/share/classes/java/util/logging/XMLFormatter.java index c3abc2ee9f7..a4f42248011 100644 --- a/src/java.logging/share/classes/java/util/logging/XMLFormatter.java +++ b/src/java.logging/share/classes/java/util/logging/XMLFormatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -219,7 +219,7 @@ public String format(LogRecord record) { } sb.append(" "); - sb.append(record.getThreadID()); + sb.append(record.getLongThreadID()); sb.append("\n"); if (record.getMessage() != null) { diff --git a/src/java.naming/share/classes/module-info.java b/src/java.naming/share/classes/module-info.java index cba5a151219..f56a5dff438 100644 --- a/src/java.naming/share/classes/module-info.java +++ b/src/java.naming/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,41 @@ /** * Defines the Java Naming and Directory Interface (JNDI) API. + *

+ * Common standard JNDI environment properties that may be supported + * by JNDI providers are defined and documented in + * {@link javax.naming.Context}. Specific JNDI provider implementations + * may also support other environment properties, which are specific + * to their implementation. + * + * @implNote + * The following implementation specific properties are supported by the + * default LDAP Naming Service Provider implementation in the JDK: + *

    + *
  • {@code com.sun.jndi.ldap.connect.timeout}: + *
    The value of this property is the string representation + * of an integer representing the connection timeout in + * milliseconds. If the LDAP provider cannot establish a + * connection within that period, it aborts the connection attempt. + * The integer should be greater than zero. An integer less than + * or equal to zero means to use the network protocol's (i.e., TCP's) + * timeout value. + *
    If this property is not specified, the default is to wait + * for the connection to be established or until the underlying + * network times out. + *
  • + *
  • {@code com.sun.jndi.ldap.read.timeout}: + *
    The value of this property is the string representation + * of an integer representing the read timeout in milliseconds + * for LDAP operations. If the LDAP provider cannot get a LDAP + * response within that period, it aborts the read attempt. The + * integer should be greater than zero. An integer less than or + * equal to zero means no read timeout is specified which is equivalent + * to waiting for the response infinitely until it is received. + *
    If this property is not specified, the default is to wait + * for the response until it is received. + *
  • + *
* * @provides javax.naming.ldap.spi.LdapDnsProvider * @@ -56,4 +91,3 @@ provides java.security.Provider with sun.security.provider.certpath.ldap.JdkLDAP; } - diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java index aea205a78f2..e650bea8ec5 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchInstruction.java @@ -30,7 +30,7 @@ * LOOKUPSWITCH and TABLESWITCH. * * @see InstructionList - * @LastModified: Jan 2020 + * @LastModified: July 2020 */ public abstract class BranchInstruction extends Instruction implements InstructionTargeter { @@ -230,6 +230,23 @@ public boolean containsTarget( final InstructionHandle ih ) { return target == ih; } + /** + * Updates the opcode. Before changing the opcode, reset the target so that + * the old instruction is removed from the HashSet and the new one then added. + * @param opcode the opcode + */ + @Override + void setOpcode( final short opcode ) { + if (target == null) { + super.setOpcode(opcode); + } else { + // reset target before changing the opcode + InstructionHandle t = target; + setTarget(null); + super.setOpcode(opcode); + setTarget(t); + } + } /** * Inform target that it's not targeted anymore. diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java index 08f801a0bb4..20188a9f16a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java @@ -29,7 +29,7 @@ /** * Abstract super class for all Java byte codes. * - * @LastModified: Jan 2020 + * @LastModified: July 2020 */ public abstract class Instruction implements Cloneable { @@ -511,7 +511,7 @@ public int getLength() { /** * Needed in readInstruction and subclasses in this package */ - final void setOpcode( final short opcode ) { + void setOpcode( final short opcode ) { this.opcode = opcode; } diff --git a/src/java.xml/share/classes/javax/xml/stream/package-info.java b/src/java.xml/share/classes/javax/xml/stream/package-info.java index 9abed31ca51..3b917b047e5 100644 --- a/src/java.xml/share/classes/javax/xml/stream/package-info.java +++ b/src/java.xml/share/classes/javax/xml/stream/package-info.java @@ -41,8 +41,8 @@ *

* StAX supports plugability with {@link XMLInputFactory} and * {@link XMLOutputFactory} that define how an implementation is - * located through a process as described in the {@link newFactory} - * method. + * located through a process as described in the {@code newFactory} + * methods. * * * @since 1.6 diff --git a/src/java.xml/share/classes/org/xml/sax/package-info.java b/src/java.xml/share/classes/org/xml/sax/package-info.java index 38b25e33dc7..ded57f86408 100644 --- a/src/java.xml/share/classes/org/xml/sax/package-info.java +++ b/src/java.xml/share/classes/org/xml/sax/package-info.java @@ -27,7 +27,6 @@ * Provides the interfaces for the Simple API for XML (SAX). Supports both * the SAX1 and SAX2 APIs. * - *

*

SAX2 Standard Feature Flags

* *

diff --git a/src/jdk.accessibility/windows/native/common/AccessBridgeStatusWindow.rc b/src/jdk.accessibility/windows/native/common/AccessBridgeStatusWindow.rc index 9659f859740..9a388c06e97 100644 --- a/src/jdk.accessibility/windows/native/common/AccessBridgeStatusWindow.rc +++ b/src/jdk.accessibility/windows/native/common/AccessBridgeStatusWindow.rc @@ -1,174 +1,126 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" -#include "accessBridgeResource.h" - -#define XSTR(x) STR(x) -#define STR(x) #x - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#define APSTUDIO_HIDDEN_SYMBOLS -#include "windows.h" -#undef APSTUDIO_HIDDEN_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -ACCESSBRIDGESTATUSWINDOW DIALOGEX 160, 78, 209, 163 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -EXSTYLE WS_EX_CLIENTEDGE -CAPTION "Access Bridge status" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - EDITTEXT cVMID,67,23,121,13,ES_READONLY - EDITTEXT cStatusText,40,147,162,13,ES_READONLY - LTEXT "Java VM ID:",IDC_STATIC,23,25,40,8 - LTEXT "Status:",IDC_STATIC,11,149,23,8 - EDITTEXT cWindowsID,67,39,121,13,ES_READONLY - LTEXT "Windows ID:",IDC_STATIC,21,41,42,8 - EDITTEXT cCallInfo,12,65,184,75,ES_MULTILINE | ES_AUTOVSCROLL | - ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL - GROUPBOX "Call info",IDC_STATIC,4,55,197,90 - EDITTEXT cInvokedByText,67,1,121,13,ES_READONLY - LTEXT "Invoked by:",IDC_STATIC,25,3,38,8 -END - -IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95 -STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Dialog" -FONT 8, "MS Sans Serif" -BEGIN - DEFPUSHBUTTON "OK",IDOK,129,7,50,14 - PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 -END - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#include ""windows.h""\r\n" - "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO DISCARDABLE -BEGIN - "ACCESSBRIDGESTATUSWINDOW", DIALOG - BEGIN - LEFTMARGIN, 4 - RIGHTMARGIN, 202 - BOTTOMMARGIN, 160 - END - - "IDD_DIALOG1", DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 179 - TOPMARGIN, 7 - BOTTOMMARGIN, 88 - END -END -#endif // APSTUDIO_INVOKED - - -#ifndef _MAC -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION JDK_FVER - PRODUCTVERSION JDK_FVER - FILEFLAGSMASK 0x3fL -#ifdef DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE JDK_FTYPE - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "Java Access Bridge" "\0" - VALUE "CompanyName", XSTR(JDK_COMPANY) "\0" - VALUE "FileDescription", XSTR(JDK_FILEDESC) "\0" - VALUE "FileVersion", XSTR(JDK_VER) "\0" - VALUE "Full Version", XSTR(JDK_VERSION_STRING) "\0" - VALUE "InternalName", XSTR(JDK_INTERNAL_NAME) "\0" - VALUE "LegalCopyright", XSTR(JDK_COPYRIGHT) "\0" - VALUE "OriginalFilename", XSTR(JDK_FNAME) "\0" - VALUE "ProductName", XSTR(JDK_NAME) "\0" - VALUE "ProductVersion", XSTR(JDK_VER) "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // !_MAC - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED +// +// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// 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. +// + +#define JDK_COMMENTS Java Access Bridge +#define JDK_FILEOS 0x40004L + +#include "version.rc" + +#include "resource.h" +#include "accessBridgeResource.h" + +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_READONLY_SYMBOLS +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +ACCESSBRIDGESTATUSWINDOW DIALOGEX 160, 78, 209, 163 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_CLIENTEDGE +CAPTION "Access Bridge status" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + EDITTEXT cVMID,67,23,121,13,ES_READONLY + EDITTEXT cStatusText,40,147,162,13,ES_READONLY + LTEXT "Java VM ID:",IDC_STATIC,23,25,40,8 + LTEXT "Status:",IDC_STATIC,11,149,23,8 + EDITTEXT cWindowsID,67,39,121,13,ES_READONLY + LTEXT "Windows ID:",IDC_STATIC,21,41,42,8 + EDITTEXT cCallInfo,12,65,184,75,ES_MULTILINE | ES_AUTOVSCROLL | + ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL + GROUPBOX "Call info",IDC_STATIC,4,55,197,90 + EDITTEXT cInvokedByText,67,1,121,13,ES_READONLY + LTEXT "Invoked by:",IDC_STATIC,25,3,38,8 +END + +IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 186, 95 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,24,50,14 +END + +#ifdef APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + "ACCESSBRIDGESTATUSWINDOW", DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 202 + BOTTOMMARGIN, 160 + END + + "IDD_DIALOG1", DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END +END + +#endif // APSTUDIO_INVOKED diff --git a/src/jdk.accessibility/windows/native/jaccessinspector/jaccessinspectorWindow.rc b/src/jdk.accessibility/windows/native/jaccessinspector/jaccessinspectorWindow.rc index 24dfeb20083..fcddea56446 100644 --- a/src/jdk.accessibility/windows/native/jaccessinspector/jaccessinspectorWindow.rc +++ b/src/jdk.accessibility/windows/native/jaccessinspector/jaccessinspectorWindow.rc @@ -1,28 +1,41 @@ -// Microsoft Visual C++ generated resource script. // +// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// 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 "version.rc" #include "jaccessinspectorResource.h" -#define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // +#define APSTUDIO_READONLY_SYMBOLS #define APSTUDIO_HIDDEN_SYMBOLS #include "windows.h" #undef APSTUDIO_HIDDEN_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - ///////////////////////////////////////////////////////////////////////////// // // Dialog @@ -55,6 +68,7 @@ END #ifdef APSTUDIO_INVOKED + ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE @@ -79,15 +93,11 @@ BEGIN "\0" END -#endif // APSTUDIO_INVOKED - - ///////////////////////////////////////////////////////////////////////////// // // DESIGNINFO // -#ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO BEGIN "JACCESSINSPECTORWINDOW", DIALOG @@ -170,53 +180,6 @@ BEGIN END END - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -// Need 2 defines so macro argument to XSTR will get expanded before quoting. -#define XSTR(x) STR(x) -#define STR(x) #x - -VS_VERSION_INFO VERSIONINFO - FILEVERSION JDK_FVER - PRODUCTVERSION JDK_FVER - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - // FILEOS 0x4 is Win32, 0x40004 is Win32 NT only - FILEOS 0x4L - // FILETYPE should be 0x1 for .exe and 0x2 for .dll - FILETYPE JDK_FTYPE - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "CompanyName", XSTR(JDK_COMPANY) "\0" - VALUE "FileDescription", XSTR(JDK_FILEDESC) "\0" - VALUE "FileVersion", XSTR(JDK_VER) "\0" - VALUE "Full Version", XSTR(JDK_VERSION_STRING) "\0" - VALUE "InternalName", XSTR(JDK_INTERNAL_NAME) "\0" - VALUE "LegalCopyright", XSTR(JDK_COPYRIGHT) "\0" - VALUE "OriginalFilename", XSTR(JDK_FNAME) "\0" - VALUE "ProductName", XSTR(JDK_NAME) "\0" - VALUE "ProductVersion", XSTR(JDK_VER) "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END - - ///////////////////////////////////////////////////////////////////////////// // // Accelerator @@ -231,19 +194,3 @@ BEGIN VK_PRIOR, cPreviousMessage, VIRTKEY, CONTROL, NOINVERT "X", cClearMessageHistory, VIRTKEY, CONTROL, NOINVERT END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalkerWindow.rc b/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalkerWindow.rc index 5d52708f368..f9e23cb3abf 100644 --- a/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalkerWindow.rc +++ b/src/jdk.accessibility/windows/native/jaccesswalker/jaccesswalkerWindow.rc @@ -1,28 +1,41 @@ -//Microsoft Developer Studio generated resource script. // +// Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// 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 "version.rc" #include "jaccesswalkerResource.h" -#define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // +#define APSTUDIO_READONLY_SYMBOLS #define APSTUDIO_HIDDEN_SYMBOLS #include "windows.h" #undef APSTUDIO_HIDDEN_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - ///////////////////////////////////////////////////////////////////////////// // // Dialog @@ -51,8 +64,8 @@ BEGIN ES_READONLY | WS_VSCROLL END - #ifdef APSTUDIO_INVOKED + ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE @@ -77,15 +90,11 @@ BEGIN "\0" END -#endif // APSTUDIO_INVOKED - - ///////////////////////////////////////////////////////////////////////////// // // DESIGNINFO // -#ifdef APSTUDIO_INVOKED GUIDELINES DESIGNINFO DISCARDABLE BEGIN "JACCESSWALKERWINDOW", DIALOG @@ -100,8 +109,8 @@ BEGIN RIGHTMARGIN, 287 END END -#endif // APSTUDIO_INVOKED +#endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // @@ -122,7 +131,6 @@ BEGIN END END - PopupMenu MENU { POPUP "" @@ -130,53 +138,3 @@ PopupMenu MENU MENUITEM "Display Accessibility Information", cAPIPopupItem } } - - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -// Need 2 defines so macro argument to XSTR will get expanded before quoting. -#define XSTR(x) STR(x) -#define STR(x) #x - -VS_VERSION_INFO VERSIONINFO - FILEVERSION JDK_FVER - PRODUCTVERSION JDK_FVER - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - // FILEOS 0x4 is Win32, 0x40004 is Win32 NT only - FILEOS 0x4L - // FILETYPE should be 0x1 for .exe and 0x2 for .dll - FILETYPE JDK_FTYPE - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "000004b0" - BEGIN - VALUE "CompanyName", XSTR(JDK_COMPANY) "\0" - VALUE "FileDescription", XSTR(JDK_FILEDESC) "\0" - VALUE "FileVersion", XSTR(JDK_VER) "\0" - VALUE "Full Version", XSTR(JDK_VERSION_STRING) "\0" - VALUE "InternalName", XSTR(JDK_INTERNAL_NAME) "\0" - VALUE "LegalCopyright", XSTR(JDK_COPYRIGHT) "\0" - VALUE "OriginalFilename", XSTR(JDK_FNAME) "\0" - VALUE "ProductName", XSTR(JDK_NAME) "\0" - VALUE "ProductVersion", XSTR(JDK_VER) "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0, 1200 - END -END 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 662c556ac5e..f8878d7fd3e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2435,7 +2435,8 @@ protected void append(char ch) { @Override protected void append(byte[] ba) { - sb.append(new String(ba)); + Name name = names.fromUtf(ba); + sb.append(name.toString()); } @Override diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java index 37b03acadb5..e41d46b8dfb 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ModuleNameReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package com.sun.tools.javac.jvm; import com.sun.tools.javac.util.ByteBuffer; +import com.sun.tools.javac.util.Convert; import com.sun.tools.javac.util.Name.NameMapper; import java.io.IOException; @@ -147,8 +148,9 @@ int nextInt() { NameMapper utf8Mapper(boolean internalize) { return internalize ? - (buf, offset, len) -> new String(ClassFile.internalize(buf, offset, len)) : - String::new; + (buf, offset, len) -> + Convert.utf2string(ClassFile.internalize(buf, offset, len)) : + Convert::utf2string; } } diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp index 9e8be03e04e..ca8b6208019 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/LinuxDebuggerLocal.cpp @@ -414,7 +414,13 @@ JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLo struct ps_prochandle* ph = get_proc_handle(env, this_obj); if (get_lwp_regs(ph, lwp_id, &gregs) != true) { - THROW_NEW_DEBUGGER_EXCEPTION_("get_thread_regs failed for a lwp", 0); + // This is not considered fatal and does happen on occassion, usually with an + // ESRCH error. The root cause is not fully understood, but by ignoring this error + // and returning NULL, stacking walking code will get null registers and fallback + // to using the "last java frame" if setup. + fprintf(stdout, "WARNING: getThreadIntegerRegisterSet0: get_lwp_regs failed for lwp (%d)\n", lwp_id); + fflush(stdout); + return NULL; } #undef NPRGREG diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c index c1fdf0f7496..72d496f5224 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_proc.c @@ -140,7 +140,8 @@ static bool process_get_lwp_regs(struct ps_prochandle* ph, pid_t pid, struct use #ifdef PTRACE_GETREGS_REQ if (ptrace_getregs(PTRACE_GETREGS_REQ, pid, user, NULL) < 0) { - print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp %d\n", pid); + print_debug("ptrace(PTRACE_GETREGS, ...) failed for lwp(%d) errno(%d) \"%s\"\n", pid, + errno, strerror(errno)); return false; } return true; diff --git a/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m b/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m index 351659f35a5..fdc99b1e33b 100644 --- a/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m +++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m @@ -600,7 +600,7 @@ jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, lo JNIEnv *env, jobject this_obj, jlong thread_id) { - print_debug("getThreadRegisterSet0 called\n"); + print_debug("getThreadIntegerRegisterSet0 called\n"); struct ps_prochandle* ph = get_proc_handle(env, this_obj); if (ph != NULL && ph->core != NULL) { @@ -620,7 +620,13 @@ jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, lo result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count); if (result != KERN_SUCCESS) { - print_error("getregs: thread_get_state(%d) failed (%d)\n", tid, result); + // This is not considered fatal. Unlike on Linux and Windows, we haven't seen a + // failure to get thread registers, but if it were to fail the response should + // be the same. By ignoring this error and returning NULL, stacking walking code + // will get null registers and fallback to using the "last java frame" if setup. + fprintf(stdout, "WARNING: getThreadIntegerRegisterSet0: thread_get_state failed (%d) for thread (%d)\n", + result, tid); + fflush(stdout); return NULL; } @@ -681,25 +687,25 @@ jlongArray getThreadIntegerRegisterSetFromCore(JNIEnv *env, jobject this_obj, lo */ JNIEXPORT jint JNICALL Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0( - JNIEnv *env, jobject this_obj, jint tid) + JNIEnv *env, jobject this_obj, jint tid) { print_debug("translateTID0 called on tid = 0x%x\n", (int)tid); kern_return_t result; thread_t foreign_tid, usable_tid; mach_msg_type_name_t type; - + foreign_tid = tid; - + task_t gTask = getTask(env, this_obj); - result = mach_port_extract_right(gTask, foreign_tid, - MACH_MSG_TYPE_COPY_SEND, + result = mach_port_extract_right(gTask, foreign_tid, + MACH_MSG_TYPE_COPY_SEND, &usable_tid, &type); if (result != KERN_SUCCESS) return -1; - + print_debug("translateTID0: 0x%x -> 0x%x\n", foreign_tid, usable_tid); - + return (jint) usable_tid; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java index 91c561d0abf..17f0aa4008b 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java @@ -167,7 +167,7 @@ public WorkerThreadTask execute(WorkerThreadTask task) throws DebuggerException } catch (InterruptedException x) {} } if (lastException != null) { - throw new DebuggerException(lastException); + throw new DebuggerException(lastException.getMessage(), lastException); } else { return task; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java index 0d637f30f14..c52d3a51d54 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,8 +67,12 @@ public String toString() { public ThreadContext getContext() throws IllegalThreadStateException { long[] data = debugger.getThreadIntegerRegisterSet(unique_thread_id); ThreadContext context = BsdThreadContextFactory.createThreadContext(debugger); - for (int i = 0; i < data.length; i++) { - context.setRegister(i, data[i]); + // null means we failed to get the register set for some reason. The caller + // is responsible for dealing with the set of null registers in that case. + if (data != null) { + for (int i = 0; i < data.length; i++) { + context.setRegister(i, data[i]); + } } return context; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java index 01d9b06dcd1..5d7f85e8396 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/bsd/amd64/BsdAMD64CFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,8 +60,13 @@ public CFrame sender(ThreadProxy thread) { return null; } + // Check alignment of rbp + if (dbg.getAddressValue(rbp) % ADDRESS_SIZE != 0) { + return null; + } + Address nextRBP = rbp.getAddressAt( 0 * ADDRESS_SIZE); - if (nextRBP == null) { + if (nextRBP == null || nextRBP.lessThanOrEqual(rbp)) { return null; } Address nextPC = rbp.getAddressAt( 1 * ADDRESS_SIZE); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java index 4b857e51c58..a9a270afe87 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxDebuggerLocal.java @@ -186,7 +186,7 @@ public WorkerThreadTask execute(WorkerThreadTask task) throws DebuggerException } catch (InterruptedException x) {} } if (lastException != null) { - throw new DebuggerException(lastException); + throw new DebuggerException(lastException.getMessage(), lastException); } else { return task; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThread.java index 52307b9cdcf..3fe795d34bc 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThread.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/LinuxThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,8 +73,12 @@ public String toString() { public ThreadContext getContext() throws IllegalThreadStateException { long[] data = debugger.getThreadIntegerRegisterSet(lwp_id); ThreadContext context = LinuxThreadContextFactory.createThreadContext(debugger); - for (int i = 0; i < data.length; i++) { - context.setRegister(i, data[i]); + // null means we failed to get the register set for some reason. The caller + // is responsible for dealing with the set of null registers in that case. + if (data != null) { + for (int i = 0; i < data.length; i++) { + context.setRegister(i, data[i]); + } } return context; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java index ec5aea35e8c..377650a0a1c 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,9 +30,9 @@ class WindbgAMD64Thread implements ThreadProxy { private WindbgDebugger debugger; - private long sysId; + private long sysId; // SystemID for Windows thread, stored in OSThread::_thread_id private boolean gotID; - private long id; + private long id; // ThreadID for Windows thread, returned by GetThreadIdBySystemId // The address argument must be the address of the OSThread::_thread_id WindbgAMD64Thread(WindbgDebugger debugger, Address addr) { @@ -50,8 +50,12 @@ class WindbgAMD64Thread implements ThreadProxy { public ThreadContext getContext() throws IllegalThreadStateException { long[] data = debugger.getThreadIntegerRegisterSet(getThreadID()); WindbgAMD64ThreadContext context = new WindbgAMD64ThreadContext(debugger); - for (int i = 0; i < data.length; i++) { - context.setRegister(i, data[i]); + // null means we failed to get the register set for some reason. The caller + // is responsible for dealing with the set of null registers in that case. + if (data != null) { + for (int i = 0; i < data.length; i++) { + context.setRegister(i, data[i]); + } } return context; } @@ -86,6 +90,7 @@ public String toString() { private long getThreadID() { if (!gotID) { id = debugger.getThreadIdFromSysId(sysId); + gotID = true; } return id; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64CurrentFrameGuess.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64CurrentFrameGuess.java index 9963b196354..e5f7e8892c1 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64CurrentFrameGuess.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64CurrentFrameGuess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2019, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -138,7 +138,16 @@ public boolean run(long regionInBytesToSearch) { setValues(curSP, null, pc); return true; } + Frame oldFrame = frame; frame = frame.sender(map); + if (frame.getSP().lessThanOrEqual(oldFrame.getSP())) { + // Frame points to itself or to a location in the wrong direction. + // Break the loop and move on to next offset. + if (DEBUG) { + System.out.println("CurrentFrameGuess: frame <= oldFrame: " + frame); + } + break; + } } } catch (Exception e) { if (DEBUG) { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java index 59be720a155..d4bcbc1694d 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/amd64/AMD64CurrentFrameGuess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,8 +28,11 @@ import sun.jvm.hotspot.debugger.amd64.*; import sun.jvm.hotspot.code.*; import sun.jvm.hotspot.interpreter.*; +import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.runtime.x86.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.utilities.*; /**

Should be able to be used on all amd64 platforms we support (Linux/amd64) to implement JavaThread's @@ -62,25 +65,135 @@ public AMD64CurrentFrameGuess(AMD64ThreadContext context, this.thread = thread; } + private boolean validateInterpreterFrame(Address sp, Address fp, Address pc) { + VM vm = VM.getVM(); + X86Frame f = new X86Frame(sp, fp, pc); + + // First validate that frame->method is really a Method* + Method method = null; + try { + method = f.getInterpreterFrameMethod(); + } catch (WrongTypeException | AddressException | NullPointerException e) { + // This just means frame->method is not valid. + if (DEBUG) { + System.out.println("CurrentFrameGuess: frame->method is invalid"); + } + } + + // Next make sure frame->bcp is really in the method's bytecodes + if (method != null && f.getInterpreterFrameBCP() != null) { + if (method.getConstMethod().isAddressInMethod(f.getInterpreterFrameBCP())) { + // All's good. This is the normal path when the PC is in the interpreter. + // The cases below are all exceptionally rare. + setValues(sp, fp, pc); + return true; + } else { + if (DEBUG) { + System.out.println("CurrentFrameGuess: frame->bcp is invalid"); + } + } + } + + // Either frame->method is not a Method* or frame->bcp is not valid. That means either + // we have pushed the new interpreter frame, but have not intialized it yet, or + // we have yet to push the new interpreter frame, and the "current" frame is not an + // interpreter frame. Figure out which is the case. + + // Try to find the return address in RAX or on the stack. If we can't + // find what appears to be a valid codecache address in either of these + // two locations, then we cannot determine the frame. + Address returnAddress = context.getRegisterAsAddress(AMD64ThreadContext.RAX); + CodeCache c = VM.getVM().getCodeCache(); + if (returnAddress == null || !c.contains(returnAddress)) { + returnAddress = sp.getAddressAt(0); // check top of stack + if (returnAddress == null || !c.contains(returnAddress)) { + if (DEBUG) { + System.out.println("CurrentFrameGuess: Cannot find valid returnAddress"); + } + setValues(sp, fp, pc); + return false; // couldn't find a valid PC for frame. + } else { + if (DEBUG) { + System.out.println("CurrentFrameGuess: returnAddress found on stack: " + returnAddress); + } + } + } else { + if (DEBUG) { + System.out.println("CurrentFrameGuess: returnAddress found in RAX: " + returnAddress); + } + } + + // See what return address is stored in the frame. Most likely it is not valid, but + // its validity will help us determine the state of the new frame push. + Address returnAddress2 = null; + try { + returnAddress2 = f.getSenderPC(); + } catch (AddressException e) { + // Just ignore. This is expected sometimes. + if (DEBUG) { + System.out.println("CurrentFrameGuess: senderPC is invalid"); + } + } + if (DEBUG) { + System.out.println("CurrentFrameGuess: returnAddress2: " + returnAddress2); + } + + if (returnAddress.equals(returnAddress2)) { + // If these two ways of fetching the return address produce the same address, + // then that means we have pushed the new frame, but have not finished + // initializing it yet. Otherwise we would also have found a valid frame->method + // and frame->bcp. Because this frame is incomplete, we instead use + // the previous frame as the current frame. + if (DEBUG) { + System.out.println("CurrentFrameGuess: frame pushed but not initialized."); + } + sp = f.getSenderSP(); + fp = f.getLink(); + setValues(sp, fp, returnAddress); + // If this previous frame is interpreted, then we are done and setValues() has been + // called with a valid interpreter frame. Otherwise return false and the caller will + // need to determine frame. + if (vm.getInterpreter().contains(returnAddress)) { + if (DEBUG) { + System.out.println("CurrentFrameGuess: Interpreted: using previous frame."); + } + return true; + } else { + if (DEBUG) { + System.out.println("CurrentFrameGuess: Not Interpreted: using previous frame."); + } + return false; + } + } else { + // We haven't even pushed the new frame yet. sp and fp are for the previous + // frame that is making the call to the interpreter. Since this frame is + // not a valid interpreter frame (we know either frame->method or frame->bcp + // are not valid), it must be something else. Assume compiled or native and + // let the caller figure it out. + setValues(sp, fp, returnAddress); + if (DEBUG) { + System.out.println("CurrentFrameGuess: Frame not yet pushed. Previous frame not interpreted."); + } + return false; + } + } + /** Returns false if not able to find a frame within a reasonable range. */ public boolean run(long regionInBytesToSearch) { Address sp = context.getRegisterAsAddress(AMD64ThreadContext.RSP); Address pc = context.getRegisterAsAddress(AMD64ThreadContext.RIP); Address fp = context.getRegisterAsAddress(AMD64ThreadContext.RBP); if (sp == null) { - // Bail out if no last java frame either - if (thread.getLastJavaSP() != null) { - setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null); - return true; - } - return false; + return checkLastJavaSP(); } Address end = sp.addOffsetTo(regionInBytesToSearch); VM vm = VM.getVM(); setValues(null, null, null); // Assume we're not going to find anything - if (vm.isJavaPCDbg(pc)) { + if (!vm.isJavaPCDbg(pc)) { + return checkLastJavaSP(); + } else { if (vm.isClientCompiler()) { // If the topmost frame is a Java frame, we are (pretty much) // guaranteed to have a viable EBP. We should be more robust @@ -96,12 +209,35 @@ public boolean run(long regionInBytesToSearch) { return true; } else { if (vm.getInterpreter().contains(pc)) { - if (DEBUG) { - System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " + - sp + ", fp = " + fp + ", pc = " + pc); + // pc points into the interpreter, but that doesn't necessarily mean the current + // frame is interpreted. We may be in interpreter method entry code before the frame + // has been pushed, or possibly after it has been pushed but before it has been + // initialized. See TemplateInterpreterGenerator::generate_normal_entry(). So we + // need to do a few sanity checks here, and try to correct the situation if + // we are in the middle of a frame push. + if (validateInterpreterFrame(sp, fp, pc)) { + if (DEBUG) { + System.out.println("CurrentFrameGuess: choosing interpreter frame: sp = " + + spFound + ", fp = " + fpFound + ", pc = " + pcFound); + } + return true; // We're done. setValues() has been called for valid interpreter frame. + } else { + // This does not appear to be a valid interpreter frame. Possibly we are in the + // middle of pushing a new frame. Update the frame values to those suggested + // by validateInterpreterFrame() and then fall through to check if it is compiled. + sp = spFound; + fp = fpFound; + pc = pcFound; + setValues(null, null, null); + if (pcFound == null) { + return false; + } + // pc may have changed, so we need to redo the isJavaPCDbg(pc) check before + // falling into code below that assumes the frame is compiled. + if (!vm.isJavaPCDbg(pc)) { + return checkLastJavaSP(); + } } - setValues(sp, fp, pc); - return true; } // For the server compiler, EBP is not guaranteed to be valid @@ -119,6 +255,9 @@ public boolean run(long regionInBytesToSearch) { // adapter frames...this is likely to be the root cause of the // failure with the simpler algorithm below. + if (DEBUG) { + System.out.println("CurrentFrameGuess: sp = " + sp + ", pc = " + pc); + } for (long offset = 0; offset < regionInBytesToSearch; offset += vm.getAddressSize()) { @@ -143,7 +282,7 @@ public boolean run(long regionInBytesToSearch) { // Frame points to itself or to a location in the wrong direction. // Break the loop and move on to next offset. if (DEBUG) { - System.out.println("AMD64CurrentFrameGuess.run: frame <= oldFrame: " + frame); + System.out.println("CurrentFrameGuess: frame <= oldFrame: " + frame); } break; } @@ -188,26 +327,28 @@ public boolean run(long regionInBytesToSearch) { } */ } - } else { - // If the current program counter was not known to us as a Java - // PC, we currently assume that we are in the run-time system - // and attempt to look to thread-local storage for saved ESP and - // EBP. Note that if these are null (because we were, in fact, - // in Java code, i.e., vtable stubs or similar, and the SA - // didn't have enough insight into the target VM to understand - // that) then we are going to lose the entire stack trace for - // the thread, which is sub-optimal. FIXME. + } + } - if (DEBUG) { - System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " + - thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP()); - } - if (thread.getLastJavaSP() == null) { - return false; // No known Java frames on stack - } - setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null); - return true; + private boolean checkLastJavaSP() { + // If the current program counter was not known to us as a Java + // PC, we currently assume that we are in the run-time system + // and attempt to look to thread-local storage for saved ESP and + // EBP. Note that if these are null (because we were, in fact, + // in Java code, i.e., vtable stubs or similar, and the SA + // didn't have enough insight into the target VM to understand + // that) then we are going to lose the entire stack trace for + // the thread, which is sub-optimal. FIXME. + + if (DEBUG) { + System.out.println("CurrentFrameGuess: choosing last Java frame: sp = " + + thread.getLastJavaSP() + ", fp = " + thread.getLastJavaFP()); + } + if (thread.getLastJavaSP() == null) { + return false; // No known Java frames on stack } + setValues(thread.getLastJavaSP(), thread.getLastJavaFP(), null); + return true; } public Address getSP() { return spFound; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java index 2eabb4b4c11..a6ba550c065 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java @@ -440,13 +440,12 @@ private Address addressOfInterpreterFrameBCX() { return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET); } - public int getInterpreterFrameBCI() { + public Address getInterpreterFrameBCP() { // FIXME: this is not atomic with respect to GC and is unsuitable // for use in a non-debugging, or reflective, system. Need to // figure out how to express this. - Address methodHandle = addressOfInterpreterFrameMethod().getAddressAt(0); - Method method = (Method)Metadata.instantiateWrapperFor(methodHandle); + Method method = getInterpreterFrameMethod(); Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0); // If we are in the top level frame then the bcp may have been set for us. If so then let it @@ -461,6 +460,12 @@ public int getInterpreterFrameBCI() { } } + return bcp; + } + + public int getInterpreterFrameBCI() { + Address bcp = getInterpreterFrameBCP(); + Method method = getInterpreterFrameMethod(); return bcpToBci(bcp, method); } diff --git a/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp b/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp index 8873d4a9302..c8ad8991b2f 100644 --- a/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp +++ b/src/jdk.hotspot.agent/windows/native/libsaproc/sawindbg.cpp @@ -42,6 +42,7 @@ #include #include +#include #define DEBUG_NO_IMPLEMENTATION #include @@ -764,9 +765,16 @@ JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal CHECK_EXCEPTION_(0); ULONG id = 0; - COM_VERIFY_OK_(ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id), - "Windbg Error: GetThreadIdBySystemId failed!", 0); - + HRESULT hr = ptrIDebugSystemObjects->GetThreadIdBySystemId((ULONG)sysId, &id); + if (hr != S_OK) { + // This is not considered fatal and does happen on occassion, usually with an + // 0x80004002 "No such interface supported". The root cause is not fully understood, + // but by ignoring this error and returning NULL, stacking walking code will get + // null registers and fallback to using the "last java frame" if setup. + printf("WARNING: GetThreadIdBySystemId failed with 0x%x for sysId (%" PRIu64 ")\n", + hr, sysId); + return -1; + } return (jlong) id; } diff --git a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/DesktopIntegration.java b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/DesktopIntegration.java index ecb236467c8..41246d4c4ee 100644 --- a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/DesktopIntegration.java +++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/DesktopIntegration.java @@ -435,8 +435,8 @@ private void addFileAssociationIconFiles(ShellCommands shellCommands) File.separatorChar, '-') + IOUtils.getSuffix( assoc.data.iconPath)); - IOUtils.copyFile(assoc.data.iconPath.toFile(), - faIconFile.srcPath().toFile()); + IOUtils.copyFile(assoc.data.iconPath, + faIconFile.srcPath()); shellCommands.addIcon(mimeType, faIconFile.installPath(), assoc.iconSize); diff --git a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxAppImageBuilder.java b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxAppImageBuilder.java index b9ba8725e6a..0afca510b09 100644 --- a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxAppImageBuilder.java +++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxAppImageBuilder.java @@ -25,7 +25,6 @@ package jdk.incubator.jpackage.internal; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; @@ -39,20 +38,21 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder { - static final BundlerParamInfo ICON_PNG = + static final BundlerParamInfo ICON_PNG = new StandardBundlerParam<>( "icon.png", - File.class, + Path.class, params -> { - File f = ICON.fetchFrom(params); - if (f != null && !f.getName().toLowerCase().endsWith(".png")) { + Path f = ICON.fetchFrom(params); + if (f != null && f.getFileName() != null && !f.getFileName() + .toString().toLowerCase().endsWith(".png")) { Log.error(MessageFormat.format( I18N.getString("message.icon-not-png"), f)); return null; } return f; }, - (s, p) -> new File(s)); + (s, p) -> Path.of(s)); final static String DEFAULT_ICON = "java32.png"; diff --git a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxDebBundler.java b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxDebBundler.java index de618a75903..b626708b7d9 100644 --- a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxDebBundler.java +++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxDebBundler.java @@ -25,7 +25,6 @@ package jdk.incubator.jpackage.internal; -import java.io.File; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; @@ -178,13 +177,13 @@ protected List getToolValidators( } @Override - protected File buildPackageBundle( + protected Path buildPackageBundle( Map replacementData, - Map params, File outputParentDir) throws + Map params, Path outputParentDir) throws PackagerException, IOException { prepareProjectConfig(replacementData, params); - adjustPermissionsRecursive(createMetaPackage(params).sourceRoot().toFile()); + adjustPermissionsRecursive(createMetaPackage(params).sourceRoot()); return buildDeb(params, outputParentDir); } @@ -309,12 +308,12 @@ protected List verifyOutputBundle( * * This cannot be directly backport to 22u which is built with 1.6 */ - private void setPermissions(File file, String permissions) { + private void setPermissions(Path file, String permissions) { Set filePermissions = PosixFilePermissions.fromString(permissions); try { - if (file.exists()) { - Files.setPosixFilePermissions(file.toPath(), filePermissions); + if (Files.exists(file)) { + Files.setPosixFilePermissions(file, filePermissions); } } catch (IOException ex) { Log.error(ex.getMessage()); @@ -335,16 +334,16 @@ public static boolean isDebian() { return false; } - private void adjustPermissionsRecursive(File dir) throws IOException { - Files.walkFileTree(dir.toPath(), new SimpleFileVisitor() { + private void adjustPermissionsRecursive(Path dir) throws IOException { + Files.walkFileTree(dir, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (file.endsWith(".so") || !Files.isExecutable(file)) { - setPermissions(file.toFile(), "rw-r--r--"); + setPermissions(file, "rw-r--r--"); } else if (Files.isExecutable(file)) { - setPermissions(file.toFile(), "rwxr-xr-x"); + setPermissions(file, "rwxr-xr-x"); } return FileVisitResult.CONTINUE; } @@ -353,7 +352,7 @@ public FileVisitResult visitFile(Path file, public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { if (e == null) { - setPermissions(dir.toFile(), "rwxr-xr-x"); + setPermissions(dir, "rwxr-xr-x"); return FileVisitResult.CONTINUE; } else { // directory iteration failed @@ -383,7 +382,7 @@ void create(Map data, Map params) .setSubstitutionData(data) .saveToFile(dstFilePath); if (permissions != null) { - setPermissions(dstFilePath.toFile(), permissions); + setPermissions(dstFilePath, permissions); } } @@ -415,7 +414,7 @@ private void prepareProjectConfig(Map data, if (!StandardBundlerParam.isRuntimeInstaller(params)) { debianFiles.add(new DebianFile( - getConfig_CopyrightFile(params).toPath(), + getConfig_CopyrightFile(params), "resource.copyright-file")); } @@ -440,7 +439,7 @@ protected Map createReplacementData( return data; } - private File getConfig_CopyrightFile(Map params) { + private Path getConfig_CopyrightFile(Map params) { final String installDir = LINUX_INSTALL_DIR.fetchFrom(params); final String packageName = PACKAGE_NAME.fetchFrom(params); @@ -452,15 +451,15 @@ private File getConfig_CopyrightFile(Map params) { } return createMetaPackage(params).sourceRoot().resolve( - Path.of("/").relativize(installPath)).toFile(); + Path.of("/").relativize(installPath)); } - private File buildDeb(Map params, - File outdir) throws IOException { - File outFile = new File(outdir, + private Path buildDeb(Map params, + Path outdir) throws IOException { + Path outFile = outdir.resolve( FULL_PACKAGE_NAME.fetchFrom(params)+".deb"); Log.verbose(MessageFormat.format(I18N.getString( - "message.outputting-to-location"), outFile.getAbsolutePath())); + "message.outputting-to-location"), outFile.toAbsolutePath().toString())); PlatformPackage thePackage = createMetaPackage(params); @@ -470,13 +469,13 @@ private File buildDeb(Map params, cmdline.add("--verbose"); } cmdline.addAll(List.of("-b", thePackage.sourceRoot().toString(), - outFile.getAbsolutePath())); + outFile.toAbsolutePath().toString())); // run dpkg Executor.of(cmdline.toArray(String[]::new)).executeExpectSuccess(); Log.verbose(MessageFormat.format(I18N.getString( - "message.output-to-location"), outFile.getAbsolutePath())); + "message.output-to-location"), outFile.toAbsolutePath().toString())); return outFile; } diff --git a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxPackageBundler.java b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxPackageBundler.java index c3b90d8c6e4..a10119491bc 100644 --- a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxPackageBundler.java +++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxPackageBundler.java @@ -24,7 +24,6 @@ */ package jdk.incubator.jpackage.internal; -import java.io.File; import java.io.IOException; import java.nio.file.InvalidPathException; import java.nio.file.Path; @@ -104,21 +103,21 @@ final public String getBundleType() { } @Override - final public File execute(Map params, - File outputParentDir) throws PackagerException { - IOUtils.writableOutputDir(outputParentDir.toPath()); + final public Path execute(Map params, + Path outputParentDir) throws PackagerException { + IOUtils.writableOutputDir(outputParentDir); PlatformPackage thePackage = createMetaPackage(params); - Function initAppImageLayout = imageRoot -> { + Function initAppImageLayout = imageRoot -> { ApplicationLayout layout = appImageLayout(params); layout.pathGroup().setPath(new Object(), AppImageFile.getPathInAppImage(Path.of(""))); - return layout.resolveAt(imageRoot.toPath()); + return layout.resolveAt(imageRoot); }; try { - File appImage = StandardBundlerParam.getPredefinedAppImage(params); + Path appImage = StandardBundlerParam.getPredefinedAppImage(params); // we either have an application image or need to build one if (appImage != null) { @@ -126,7 +125,7 @@ final public File execute(Map params, thePackage.sourceApplicationLayout()); } else { final Path srcAppImageRoot = thePackage.sourceRoot().resolve("src"); - appImage = appImageBundler.execute(params, srcAppImageRoot.toFile()); + appImage = appImageBundler.execute(params, srcAppImageRoot); ApplicationLayout srcAppLayout = initAppImageLayout.apply( appImage); if (appImage.equals(PREDEFINED_RUNTIME_IMAGE.fetchFrom(params))) { @@ -137,7 +136,7 @@ final public File execute(Map params, // Application image is a newly created directory tree. // Move it. srcAppLayout.move(thePackage.sourceApplicationLayout()); - IOUtils.deleteRecursive(srcAppImageRoot.toFile()); + IOUtils.deleteRecursive(srcAppImageRoot); } } @@ -153,10 +152,10 @@ final public File execute(Map params, data.putAll(createReplacementData(params)); - File packageBundle = buildPackageBundle(Collections.unmodifiableMap( + Path packageBundle = buildPackageBundle(Collections.unmodifiableMap( data), params, outputParentDir); - verifyOutputBundle(params, packageBundle.toPath()).stream() + verifyOutputBundle(params, packageBundle).stream() .filter(Objects::nonNull) .forEachOrdered(ex -> { Log.verbose(ex.getLocalizedMessage()); @@ -240,9 +239,9 @@ abstract protected void doValidate(Map params) abstract protected Map createReplacementData( Map params) throws IOException; - abstract protected File buildPackageBundle( + abstract protected Path buildPackageBundle( Map replacementData, - Map params, File outputParentDir) throws + Map params, Path outputParentDir) throws PackagerException, IOException; final protected PlatformPackage createMetaPackage( @@ -266,7 +265,7 @@ public String name() { @Override public Path sourceRoot() { - return IMAGES_ROOT.fetchFrom(params).toPath().toAbsolutePath(); + return IMAGES_ROOT.fetchFrom(params).toAbsolutePath(); } @Override diff --git a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxRpmBundler.java b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxRpmBundler.java index 1c2f7d05c2c..4ddddf0ae91 100644 --- a/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxRpmBundler.java +++ b/src/jdk.incubator.jpackage/linux/classes/jdk/incubator/jpackage/internal/LinuxRpmBundler.java @@ -25,7 +25,6 @@ package jdk.incubator.jpackage.internal; -import java.io.File; import java.io.IOException; import java.nio.file.Path; import java.text.MessageFormat; @@ -147,9 +146,9 @@ protected List getToolValidators( } @Override - protected File buildPackageBundle( + protected Path buildPackageBundle( Map replacementData, - Map params, File outputParentDir) throws + Map params, Path outputParentDir) throws PackagerException, IOException { Path specFile = specFile(params); @@ -160,7 +159,7 @@ protected File buildPackageBundle( .setSubstitutionData(replacementData) .saveToFile(specFile); - return buildRPM(params, outputParentDir.toPath()).toFile(); + return buildRPM(params, outputParentDir); } @Override @@ -275,7 +274,7 @@ private String rpmArch() throws IOException { } private Path specFile(Map params) { - return TEMP_ROOT.fetchFrom(params).toPath().resolve(Path.of("SPECS", + return TEMP_ROOT.fetchFrom(params).resolve(Path.of("SPECS", PACKAGE_NAME.fetchFrom(params) + ".spec")); } @@ -302,7 +301,7 @@ private Path buildRPM(Map params, "--define", String.format("%%_rpmdir %s", rpmFile.getParent()), // do not use other system directories to build as current user "--define", String.format("%%_topdir %s", - TEMP_ROOT.fetchFrom(params).toPath().toAbsolutePath()), + TEMP_ROOT.fetchFrom(params).toAbsolutePath()), "--define", String.format("%%_rpmfilename %s", rpmFile.getFileName()) ).executeExpectSuccess(); diff --git a/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppImageBuilder.java b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppImageBuilder.java index 4fae1245776..3f51bc824ce 100644 --- a/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppImageBuilder.java +++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppImageBuilder.java @@ -25,8 +25,6 @@ package jdk.incubator.jpackage.internal; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.Writer; @@ -120,20 +118,21 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder { }, (s, p) -> s); - public static final BundlerParamInfo ICON_ICNS = + public static final BundlerParamInfo ICON_ICNS = new StandardBundlerParam<>( "icon.icns", - File.class, + Path.class, params -> { - File f = ICON.fetchFrom(params); - if (f != null && !f.getName().toLowerCase().endsWith(".icns")) { + Path f = ICON.fetchFrom(params); + if (f != null && f.getFileName() != null && !f.getFileName() + .toString().toLowerCase().endsWith(".icns")) { Log.error(MessageFormat.format( I18N.getString("message.icon-not-icns"), f)); return null; } return f; }, - (s, p) -> new File(s)); + (s, p) -> Path.of(s)); public static final StandardBundlerParam SIGN_BUNDLE = new StandardBundlerParam<>( @@ -242,8 +241,8 @@ public void prepareApplicationFiles(Map params) Map originalParams = new HashMap<>(params); // Generate PkgInfo - File pkgInfoFile = new File(contentsDir.toFile(), "PkgInfo"); - pkgInfoFile.createNewFile(); + Path pkgInfoFile = contentsDir.resolve("PkgInfo"); + Files.createFile(pkgInfoFile); writePkgInfo(pkgInfoFile); Path executable = macOSDir.resolve(getLauncherName(params)); @@ -290,11 +289,9 @@ public void prepareApplicationFiles(Map params) // copy file association icons for (Map fa : FILE_ASSOCIATIONS.fetchFrom(params)) { - File f = FA_ICON.fetchFrom(fa); - if (f != null && f.exists()) { - try (InputStream in2 = new FileInputStream(f)) { - Files.copy(in2, resourcesDir.resolve(f.getName())); - } + Path f = FA_ICON.fetchFrom(fa); + if (IOUtils.exists(f)) { + IOUtils.copyFile(f, resourcesDir.resolve(f.getFileName())); } } @@ -306,11 +303,11 @@ public void prepareApplicationFiles(Map params) private void copyRuntimeFiles(Map params) throws IOException { // Generate Info.plist - writeInfoPlist(contentsDir.resolve("Info.plist").toFile(), params); + writeInfoPlist(contentsDir.resolve("Info.plist"), params); // generate java runtime info.plist writeRuntimeInfoPlist( - runtimeDir.resolve("Contents/Info.plist").toFile(), params); + runtimeDir.resolve("Contents/Info.plist"), params); // copy library Path runtimeMacOSDir = Files.createDirectories( @@ -346,8 +343,8 @@ private void sign(Map params) throws IOException { } } - static File getConfig_Entitlements(Map params) { - return new File(CONFIG_ROOT.fetchFrom(params), + static Path getConfig_Entitlements(Map params) { + return CONFIG_ROOT.fetchFrom(params).resolve( getLauncherName(params) + ".entitlements"); } @@ -382,7 +379,7 @@ private String getBundleName(Map params) { } } - private void writeRuntimeInfoPlist(File file, + private void writeRuntimeInfoPlist(Path file, Map params) throws IOException { Map data = new HashMap<>(); String identifier = StandardBundlerParam.isRuntimeInstaller(params) ? @@ -427,10 +424,10 @@ private void writeBoolPlist(StringBuilder sb, String key, String value) { } } - private void writeInfoPlist(File file, Map params) + private void writeInfoPlist(Path file, Map params) throws IOException { Log.verbose(MessageFormat.format(I18N.getString( - "message.preparing-info-plist"), file.getAbsolutePath())); + "message.preparing-info-plist"), file.toAbsolutePath())); //prepare config for exe //Note: do not need CFBundleDisplayName if we don't support localization @@ -460,7 +457,7 @@ private void writeInfoPlist(File file, Map params) + "." + ((extensions == null || extensions.isEmpty()) ? "mime" : extensions.get(0)); String description = FA_DESCRIPTION.fetchFrom(fileAssociation); - File icon = FA_ICON.fetchFrom(fileAssociation); + Path icon = FA_ICON.fetchFrom(fileAssociation); bundleDocumentTypes.append(" \n"); writeStringArrayPlist(bundleDocumentTypes, "LSItemContentTypes", @@ -482,9 +479,9 @@ private void writeInfoPlist(File file, Map params) FA_MAC_LSDOCINPLACE.fetchFrom(fileAssociation)); writeBoolPlist(bundleDocumentTypes, "UISupportsDocumentBrowser", FA_MAC_UIDOCBROWSER.fetchFrom(fileAssociation)); - if (icon != null && icon.exists()) { + if (IOUtils.exists(icon)) { writeStringPlist(bundleDocumentTypes, "CFBundleTypeIconFile", - icon.getName()); + icon.getFileName().toString()); } bundleDocumentTypes.append(" \n"); @@ -496,8 +493,9 @@ private void writeInfoPlist(File file, Map params) writeStringArrayPlist(exportedTypes, "UTTypeConformsTo", FA_MAC_UTTYPECONFORMSTO.fetchFrom(fileAssociation)); - if (icon != null && icon.exists()) { - writeStringPlist(exportedTypes, "UTTypeIconFile", icon.getName()); + if (IOUtils.exists(icon)) { + writeStringPlist(exportedTypes, "UTTypeIconFile", + icon.getFileName().toString()); } exportedTypes.append("\n") .append(" UTTypeTagSpecification\n") @@ -532,11 +530,11 @@ private void writeInfoPlist(File file, Map params) .saveToFile(file); } - private void writePkgInfo(File file) throws IOException { + private void writePkgInfo(Path file) throws IOException { //hardcoded as it does not seem we need to change it ever String signature = "????"; - try (Writer out = Files.newBufferedWriter(file.toPath())) { + try (Writer out = Files.newBufferedWriter(file)) { out.write(OS_TYPE_CODE + signature); out.flush(); } @@ -557,7 +555,7 @@ public static void addNewKeychain(Map params) } // get current keychain list - String keyChainPath = new File (keyChain).getAbsolutePath().toString(); + String keyChainPath = Path.of(keyChain).toAbsolutePath().toString(); List keychainList = new ArrayList<>(); int ret = IOUtils.getProcessOutput( keychainList, "security", "list-keychains"); @@ -621,7 +619,7 @@ public static void restoreKeychainList(Map params) static void signAppBundle( Map params, Path appLocation, - String signingIdentity, String identifierPrefix, File entitlements) + String signingIdentity, String identifierPrefix, Path entitlements) throws IOException { AtomicReference toThrow = new AtomicReference<>(); String appExecutable = "/Contents/MacOS/" + APP_NAME.fetchFrom(params); @@ -683,8 +681,7 @@ static void signAppBundle( try { Set oldPermissions = Files.getPosixFilePermissions(p); - File f = p.toFile(); - f.setWritable(true, true); + p.toFile().setWritable(true, true); ProcessBuilder pb = new ProcessBuilder(args); @@ -798,17 +795,15 @@ private static String extractBundleIdentifier(Map params) { } try { - File infoPList = new File(PREDEFINED_APP_IMAGE.fetchFrom(params) + - File.separator + "Contents" + - File.separator + "Info.plist"); + Path infoPList = PREDEFINED_APP_IMAGE.fetchFrom(params).resolve("Contents"). + resolve("Info.plist"); DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance(); dbf.setFeature("http://apache.org/xml/features/" + "nonvalidating/load-external-dtd", false); DocumentBuilder b = dbf.newDocumentBuilder(); - org.w3c.dom.Document doc = b.parse(new FileInputStream( - infoPList.getAbsolutePath())); + org.w3c.dom.Document doc = b.parse(Files.newInputStream(infoPList)); XPath xPath = XPathFactory.newInstance().newXPath(); // Query for the value of element preceding diff --git a/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppStoreBundler.java b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppStoreBundler.java index 186c13659cf..b83c6c31cb0 100644 --- a/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppStoreBundler.java +++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacAppStoreBundler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,8 @@ package jdk.incubator.jpackage.internal; -import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; @@ -103,21 +104,21 @@ public class MacAppStoreBundler extends MacBaseInstallerBundler { params -> "-MacAppStore", (s, p) -> s); - public File bundle(Map params, - File outdir) throws PackagerException { + public Path bundle(Map params, + Path outdir) throws PackagerException { Log.verbose(MessageFormat.format(I18N.getString( "message.building-bundle"), APP_NAME.fetchFrom(params))); - IOUtils.writableOutputDir(outdir.toPath()); + IOUtils.writableOutputDir(outdir); // first, load in some overrides // icns needs @2 versions, so load in the @2 default params.put(DEFAULT_ICNS_ICON.getID(), TEMPLATE_BUNDLE_ICON_HIDPI); // now we create the app - File appImageDir = APP_IMAGE_TEMP_ROOT.fetchFrom(params); + Path appImageDir = APP_IMAGE_TEMP_ROOT.fetchFrom(params); try { - appImageDir.mkdirs(); + Files.createDirectories(appImageDir); try { MacAppImageBuilder.addNewKeychain(params); @@ -126,7 +127,7 @@ public File bundle(Map params, } // first, make sure we don't use the local signing key params.put(DEVELOPER_ID_APP_SIGNING_KEY.getID(), null); - File appLocation = prepareAppBundle(params); + Path appLocation = prepareAppBundle(params); String signingIdentity = MAC_APP_STORE_APP_SIGNING_KEY.fetchFrom(params); @@ -134,7 +135,7 @@ public File bundle(Map params, BUNDLE_ID_SIGNING_PREFIX.fetchFrom(params); MacAppImageBuilder.prepareEntitlements(params); - MacAppImageBuilder.signAppBundle(params, appLocation.toPath(), + MacAppImageBuilder.signAppBundle(params, appLocation, signingIdentity, identifierPrefix, MacAppImageBuilder.getConfig_Entitlements(params)); MacAppImageBuilder.restoreKeychainList(params); @@ -142,10 +143,10 @@ public File bundle(Map params, ProcessBuilder pb; // create the final pkg file - File finalPKG = new File(outdir, INSTALLER_NAME.fetchFrom(params) + Path finalPKG = outdir.resolve(INSTALLER_NAME.fetchFrom(params) + INSTALLER_SUFFIX.fetchFrom(params) + ".pkg"); - outdir.mkdirs(); + Files.createDirectories(outdir); String installIdentify = MAC_APP_STORE_PKG_SIGNING_KEY.fetchFrom(params); @@ -164,7 +165,7 @@ public File bundle(Map params, buildOptions.add("--keychain"); buildOptions.add(keychainName); } - buildOptions.add(finalPKG.getAbsolutePath()); + buildOptions.add(finalPKG.toAbsolutePath().toString()); pb = new ProcessBuilder(buildOptions); @@ -243,8 +244,8 @@ public boolean validate(Map params) } @Override - public File execute(Map params, - File outputParentDir) throws PackagerException { + public Path execute(Map params, + Path outputParentDir) throws PackagerException { return bundle(params, outputParentDir); } diff --git a/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacBaseInstallerBundler.java b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacBaseInstallerBundler.java index 545e82d811c..569cb6836cd 100644 --- a/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacBaseInstallerBundler.java +++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacBaseInstallerBundler.java @@ -26,10 +26,10 @@ package jdk.incubator.jpackage.internal; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.nio.file.Files; +import java.nio.file.Path; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; @@ -43,21 +43,23 @@ public abstract class MacBaseInstallerBundler extends AbstractBundler { - public final BundlerParamInfo APP_IMAGE_TEMP_ROOT = + public final BundlerParamInfo APP_IMAGE_TEMP_ROOT = new StandardBundlerParam<>( "mac.app.imageRoot", - File.class, + Path.class, params -> { - File imageDir = IMAGES_ROOT.fetchFrom(params); - if (!imageDir.exists()) imageDir.mkdirs(); + Path imageDir = IMAGES_ROOT.fetchFrom(params); try { + if (!IOUtils.exists(imageDir)) { + Files.createDirectories(imageDir); + } return Files.createTempDirectory( - imageDir.toPath(), "image-").toFile(); + imageDir, "image-"); } catch (IOException e) { - return new File(imageDir, getID()+ ".image"); + return imageDir.resolve(getID()+ ".image"); } }, - (s, p) -> new File(s)); + (s, p) -> Path.of(s)); public static final BundlerParamInfo SIGNING_KEY_USER = new StandardBundlerParam<>( @@ -110,8 +112,8 @@ public MacBaseInstallerBundler() { protected void validateAppImageAndBundeler( Map params) throws ConfigException { if (PREDEFINED_APP_IMAGE.fetchFrom(params) != null) { - File applicationImage = PREDEFINED_APP_IMAGE.fetchFrom(params); - if (!applicationImage.exists()) { + Path applicationImage = PREDEFINED_APP_IMAGE.fetchFrom(params); + if (!IOUtils.exists(applicationImage)) { throw new ConfigException( MessageFormat.format(I18N.getString( "message.app-image-dir-does-not-exist"), @@ -132,14 +134,14 @@ protected void validateAppImageAndBundeler( } } - protected File prepareAppBundle(Map params) + protected Path prepareAppBundle(Map params) throws PackagerException { - File predefinedImage = + Path predefinedImage = StandardBundlerParam.getPredefinedAppImage(params); if (predefinedImage != null) { return predefinedImage; } - File appImageRoot = APP_IMAGE_TEMP_ROOT.fetchFrom(params); + Path appImageRoot = APP_IMAGE_TEMP_ROOT.fetchFrom(params); return appImageBundler.execute(params, appImageRoot); } diff --git a/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacCertificate.java b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacCertificate.java index a7229995d2a..b1c0ec78bca 100644 --- a/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacCertificate.java +++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacCertificate.java @@ -27,11 +27,11 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; import java.io.PrintStream; import java.nio.file.StandardCopyOption; import java.nio.file.Files; +import java.nio.file.Path; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -52,8 +52,8 @@ public boolean isValid() { return verifyCertificate(this.certificate); } - private static File findCertificate(String certificate) { - File result = null; + private static Path findCertificate(String certificate) { + Path result = null; List args = new ArrayList<>(); args.add("security"); @@ -68,10 +68,10 @@ private static File findCertificate(String certificate) { ProcessBuilder security = new ProcessBuilder(args); IOUtils.exec(security, false, ps); - File output = File.createTempFile("tempfile", ".tmp"); + Path output = Files.createTempFile("tempfile", ".tmp"); Files.copy(new ByteArrayInputStream(baos.toByteArray()), - output.toPath(), StandardCopyOption.REPLACE_EXISTING); + output, StandardCopyOption.REPLACE_EXISTING); result = output; } @@ -111,7 +111,7 @@ private static boolean verifyCertificate(String certificate) { boolean result = false; try { - File file = null; + Path file = null; Date certificateDate = null; try { @@ -119,12 +119,12 @@ private static boolean verifyCertificate(String certificate) { if (file != null) { certificateDate = findCertificateDate( - file.getCanonicalPath()); + file.toFile().getCanonicalPath()); } } finally { if (file != null) { - file.delete(); + Files.delete(file); } } diff --git a/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacDmgBundler.java b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacDmgBundler.java index 8787e345168..4af6e7955e7 100644 --- a/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacDmgBundler.java +++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacDmgBundler.java @@ -69,29 +69,29 @@ public class MacDmgBundler extends MacBaseInstallerBundler { params -> "", (s, p) -> s); - public File bundle(Map params, - File outdir) throws PackagerException { + public Path bundle(Map params, + Path outdir) throws PackagerException { Log.verbose(MessageFormat.format(I18N.getString("message.building-dmg"), APP_NAME.fetchFrom(params))); - IOUtils.writableOutputDir(outdir.toPath()); + IOUtils.writableOutputDir(outdir); try { - File appLocation = prepareAppBundle(params); + Path appLocation = prepareAppBundle(params); if (appLocation != null && prepareConfigFiles(params)) { - File configScript = getConfig_Script(params); - if (configScript.exists()) { + Path configScript = getConfig_Script(params); + if (IOUtils.exists(configScript)) { Log.verbose(MessageFormat.format( I18N.getString("message.running-script"), - configScript.getAbsolutePath())); + configScript.toAbsolutePath().toString())); IOUtils.run("bash", configScript); } return buildDMG(params, appLocation, outdir); } return null; - } catch (IOException ex) { + } catch (IOException | PackagerException ex) { Log.verbose(ex); throw new PackagerException(ex); } @@ -101,16 +101,19 @@ public File bundle(Map params, private void prepareDMGSetupScript(Map params) throws IOException { - File dmgSetup = getConfig_VolumeScript(params); + Path dmgSetup = getConfig_VolumeScript(params); Log.verbose(MessageFormat.format( I18N.getString("message.preparing-dmg-setup"), - dmgSetup.getAbsolutePath())); + dmgSetup.toAbsolutePath().toString())); // We need to use URL for DMG to find it. We cannot use volume name, since // user might have open DMG with same volume name already. Url should end with // '/' and it should be real path (no symbolic links). - File imageDir = IMAGES_ROOT.fetchFrom(params); - if (!imageDir.exists()) imageDir.mkdirs(); // Create it, since it does not exist + Path imageDir = IMAGES_ROOT.fetchFrom(params); + if (!Files.exists(imageDir)) { + // Create it, since it does not exist + Files.createDirectories(imageDir); + } Path rootPath = Path.of(imageDir.toString()).toRealPath(); Path volumePath = rootPath.resolve(APP_NAME.fetchFrom(params)); String volumeUrl = volumePath.toUri().toString() + File.separator; @@ -134,24 +137,24 @@ private void prepareDMGSetupScript(Map params) .saveToFile(dmgSetup); } - private File getConfig_VolumeScript(Map params) { - return new File(CONFIG_ROOT.fetchFrom(params), + private Path getConfig_VolumeScript(Map params) { + return CONFIG_ROOT.fetchFrom(params).resolve( APP_NAME.fetchFrom(params) + "-dmg-setup.scpt"); } - private File getConfig_VolumeBackground( + private Path getConfig_VolumeBackground( Map params) { - return new File(CONFIG_ROOT.fetchFrom(params), + return CONFIG_ROOT.fetchFrom(params).resolve( APP_NAME.fetchFrom(params) + "-background.tiff"); } - private File getConfig_VolumeIcon(Map params) { - return new File(CONFIG_ROOT.fetchFrom(params), + private Path getConfig_VolumeIcon(Map params) { + return CONFIG_ROOT.fetchFrom(params).resolve( APP_NAME.fetchFrom(params) + "-volume.icns"); } - private File getConfig_LicenseFile(Map params) { - return new File(CONFIG_ROOT.fetchFrom(params), + private Path getConfig_LicenseFile(Map params) { + return CONFIG_ROOT.fetchFrom(params).resolve( APP_NAME.fetchFrom(params) + "-license.plist"); } @@ -162,9 +165,9 @@ private void prepareLicense(Map params) { return; } - File licFile = new File(licFileStr); + Path licFile = Path.of(licFileStr); byte[] licenseContentOriginal = - Files.readAllBytes(licFile.toPath()); + Files.readAllBytes(licFile); String licenseInBase64 = Base64.getEncoder().encodeToString(licenseContentOriginal); @@ -205,8 +208,8 @@ private boolean prepareConfigFiles(Map params) } // name of post-image script - private File getConfig_Script(Map params) { - return new File(CONFIG_ROOT.fetchFrom(params), + private Path getConfig_Script(Map params) { + return CONFIG_ROOT.fetchFrom(params).resolve( APP_NAME.fetchFrom(params) + "-post-image.sh"); } @@ -218,9 +221,9 @@ private String findSetFileUtility() { "/usr/bin/SetFile", "/Developer/usr/bin/SetFile"}; String setFilePath = null; - for (String path: typicalPaths) { - File f = new File(path); - if (f.exists() && f.canExecute()) { + for (String path : typicalPaths) { + Path f = Path.of(path); + if (Files.exists(f) && Files.isExecutable(f)) { setFilePath = path; break; } @@ -251,9 +254,9 @@ private String findSetFileUtility() { BufferedReader br = new BufferedReader(isr); String lineRead = br.readLine(); if (lineRead != null) { - File f = new File(lineRead); - if (f.exists() && f.canExecute()) { - return f.getAbsolutePath(); + Path f = Path.of(lineRead); + if (Files.exists(f) && Files.isExecutable(f)) { + return f.toAbsolutePath().toString(); } } } catch (IOException ignored) {} @@ -261,30 +264,30 @@ private String findSetFileUtility() { return null; } - private File buildDMG( Map params, - File appLocation, File outdir) throws IOException { - File imagesRoot = IMAGES_ROOT.fetchFrom(params); - if (!imagesRoot.exists()) imagesRoot.mkdirs(); + private Path buildDMG( Map params, + Path appLocation, Path outdir) throws IOException { + boolean copyAppImage = false; + Path imagesRoot = IMAGES_ROOT.fetchFrom(params); + if (!Files.exists(imagesRoot)) { + Files.createDirectories(imagesRoot); + } - File protoDMG = new File(imagesRoot, - APP_NAME.fetchFrom(params) +"-tmp.dmg"); - File finalDMG = new File(outdir, INSTALLER_NAME.fetchFrom(params) + Path protoDMG = imagesRoot.resolve(APP_NAME.fetchFrom(params) +"-tmp.dmg"); + Path finalDMG = outdir.resolve(INSTALLER_NAME.fetchFrom(params) + INSTALLER_SUFFIX.fetchFrom(params) + ".dmg"); - File srcFolder = APP_IMAGE_TEMP_ROOT.fetchFrom(params); - File predefinedImage = - StandardBundlerParam.getPredefinedAppImage(params); + Path srcFolder = APP_IMAGE_TEMP_ROOT.fetchFrom(params); + Path predefinedImage = StandardBundlerParam.getPredefinedAppImage(params); if (predefinedImage != null) { srcFolder = predefinedImage; } else if (StandardBundlerParam.isRuntimeInstaller(params)) { - Path newRoot = Files.createTempDirectory( - TEMP_ROOT.fetchFrom(params).toPath(), "root-"); + Path newRoot = Files.createTempDirectory(TEMP_ROOT.fetchFrom(params), + "root-"); // first, is this already a runtime with // /Contents/Home - if so we need the Home dir - Path original = appLocation.toPath(); - Path home = original.resolve("Contents/Home"); - Path source = (Files.exists(home)) ? home : original; + Path home = appLocation.resolve("Contents/Home"); + Path source = (Files.exists(home)) ? home : appLocation; // Then we need to put back the /Content/Home Path root = newRoot.resolve( @@ -293,21 +296,23 @@ private File buildDMG( Map params, IOUtils.copyRecursive(source, dest); - srcFolder = newRoot.toFile(); + srcFolder = newRoot; } Log.verbose(MessageFormat.format(I18N.getString( - "message.creating-dmg-file"), finalDMG.getAbsolutePath())); + "message.creating-dmg-file"), finalDMG.toAbsolutePath())); - protoDMG.delete(); - if (finalDMG.exists() && !finalDMG.delete()) { + Files.deleteIfExists(protoDMG); + try { + Files.deleteIfExists(finalDMG); + } catch (IOException ex) { throw new IOException(MessageFormat.format(I18N.getString( "message.dmg-cannot-be-overwritten"), - finalDMG.getAbsolutePath())); + finalDMG.toAbsolutePath())); } - protoDMG.getParentFile().mkdirs(); - finalDMG.getParentFile().mkdirs(); + Files.createDirectories(protoDMG.getParent()); + Files.createDirectories(finalDMG.getParent()); String hdiUtilVerbosityFlag = VERBOSE.fetchFrom(params) ? "-verbose" : "-quiet"; @@ -317,44 +322,83 @@ private File buildDMG( Map params, hdiutil, "create", hdiUtilVerbosityFlag, - "-srcfolder", srcFolder.getAbsolutePath(), + "-srcfolder", srcFolder.toAbsolutePath().toString(), "-volname", APP_NAME.fetchFrom(params), - "-ov", protoDMG.getAbsolutePath(), + "-ov", protoDMG.toAbsolutePath().toString(), "-fs", "HFS+", "-format", "UDRW"); - IOUtils.exec(pb); + try { + IOUtils.exec(pb); + } catch (IOException ex) { + Log.verbose(ex); // Log exception + + // Creating DMG from entire app image failed, so lets try to create empty + // DMG and copy files manually. See JDK-8248059. + copyAppImage = true; + + long size = new PathGroup(Map.of(new Object(), srcFolder)).sizeInBytes(); + size += 50 * 1024 * 1024; // Add extra 50 megabytes. Actually DMG size will + // not be bigger, but it will able to hold additional 50 megabytes of data. + // We need extra room for icons and background image. When we providing + // actual files to hdiutil, it will create DMG with ~50 megabytes extra room. + pb = new ProcessBuilder( + hdiutil, + "create", + hdiUtilVerbosityFlag, + "-size", String.valueOf(size), + "-volname", APP_NAME.fetchFrom(params), + "-ov", protoDMG.toAbsolutePath().toString(), + "-fs", "HFS+"); + IOUtils.exec(pb); + } // mount temp image pb = new ProcessBuilder( hdiutil, "attach", - protoDMG.getAbsolutePath(), + protoDMG.toAbsolutePath().toString(), hdiUtilVerbosityFlag, - "-mountroot", imagesRoot.getAbsolutePath()); + "-mountroot", imagesRoot.toAbsolutePath().toString()); IOUtils.exec(pb, false, null, true); - File mountedRoot = new File(imagesRoot.getAbsolutePath(), - APP_NAME.fetchFrom(params)); + Path mountedRoot = imagesRoot.resolve(APP_NAME.fetchFrom(params)); + + // Copy app image, since we did not create DMG with it, but instead we created + // empty one. + if (copyAppImage) { + // In case of predefine app image srcFolder will point to app bundle, so if + // we use it as is we will copy content of app bundle, but we need app bundle + // folder as well. + if (srcFolder.toString().toLowerCase().endsWith(".app")) { + Path destPath = mountedRoot + .resolve(srcFolder.getFileName()); + Files.createDirectory(destPath); + IOUtils.copyRecursive(srcFolder, destPath); + } else { + IOUtils.copyRecursive(srcFolder, mountedRoot); + } + } + try { // background image - File bgdir = new File(mountedRoot, BACKGROUND_IMAGE_FOLDER); - bgdir.mkdirs(); + Path bgdir = mountedRoot.resolve(BACKGROUND_IMAGE_FOLDER); + Files.createDirectories(bgdir); IOUtils.copyFile(getConfig_VolumeBackground(params), - new File(bgdir, BACKGROUND_IMAGE)); + bgdir.resolve(BACKGROUND_IMAGE)); // We will not consider setting background image and creating link // to install-dir in DMG as critical error, since it can fail in // headless enviroment. try { pb = new ProcessBuilder("osascript", - getConfig_VolumeScript(params).getAbsolutePath()); + getConfig_VolumeScript(params).toAbsolutePath().toString()); IOUtils.exec(pb); } catch (IOException ex) { Log.verbose(ex); } // volume icon - File volumeIconFile = new File(mountedRoot, ".VolumeIcon.icns"); + Path volumeIconFile = mountedRoot.resolve(".VolumeIcon.icns"); IOUtils.copyFile(getConfig_VolumeIcon(params), volumeIconFile); @@ -366,7 +410,7 @@ private File buildDMG( Map params, if (setFileUtility != null) { //can not find utility => keep going without icon try { - volumeIconFile.setWritable(true); + volumeIconFile.toFile().setWritable(true); // The "creator" attribute on a file is a legacy attribute // but it seems Finder excepts these bytes to be // "icnC" for the volume icon @@ -374,14 +418,14 @@ private File buildDMG( Map params, pb = new ProcessBuilder( setFileUtility, "-c", "icnC", - volumeIconFile.getAbsolutePath()); + volumeIconFile.toAbsolutePath().toString()); IOUtils.exec(pb); - volumeIconFile.setReadOnly(); + volumeIconFile.toFile().setReadOnly(); pb = new ProcessBuilder( setFileUtility, "-a", "C", - mountedRoot.getAbsolutePath()); + mountedRoot.toAbsolutePath().toString()); IOUtils.exec(pb); } catch (IOException ex) { Log.error(ex.getMessage()); @@ -398,7 +442,7 @@ private File buildDMG( Map params, "detach", "-force", hdiUtilVerbosityFlag, - mountedRoot.getAbsolutePath()); + mountedRoot.toAbsolutePath().toString()); IOUtils.exec(pb); } @@ -406,19 +450,19 @@ private File buildDMG( Map params, pb = new ProcessBuilder( hdiutil, "convert", - protoDMG.getAbsolutePath(), + protoDMG.toAbsolutePath().toString(), hdiUtilVerbosityFlag, "-format", "UDZO", - "-o", finalDMG.getAbsolutePath()); + "-o", finalDMG.toAbsolutePath().toString()); IOUtils.exec(pb); //add license if needed - if (getConfig_LicenseFile(params).exists()) { + if (Files.exists(getConfig_LicenseFile(params))) { //hdiutil unflatten your_image_file.dmg pb = new ProcessBuilder( hdiutil, "unflatten", - finalDMG.getAbsolutePath() + finalDMG.toAbsolutePath().toString() ); IOUtils.exec(pb); @@ -426,9 +470,9 @@ private File buildDMG( Map params, pb = new ProcessBuilder( hdiutil, "udifrez", - finalDMG.getAbsolutePath(), + finalDMG.toAbsolutePath().toString(), "-xml", - getConfig_LicenseFile(params).getAbsolutePath() + getConfig_LicenseFile(params).toAbsolutePath().toString() ); IOUtils.exec(pb); @@ -436,18 +480,18 @@ private File buildDMG( Map params, pb = new ProcessBuilder( hdiutil, "flatten", - finalDMG.getAbsolutePath() + finalDMG.toAbsolutePath().toString() ); IOUtils.exec(pb); } //Delete the temporary image - protoDMG.delete(); + Files.deleteIfExists(protoDMG); Log.verbose(MessageFormat.format(I18N.getString( "message.output-to-location"), - APP_NAME.fetchFrom(params), finalDMG.getAbsolutePath())); + APP_NAME.fetchFrom(params), finalDMG.toAbsolutePath().toString())); return finalDMG; } @@ -488,8 +532,8 @@ public boolean validate(Map params) } @Override - public File execute(Map params, - File outputParentDir) throws PackagerException { + public Path execute(Map params, + Path outputParentDir) throws PackagerException { return bundle(params, outputParentDir); } @@ -503,8 +547,8 @@ public boolean supported(boolean runtimeInstaller) { public static boolean isSupported() { try { for (String s : required) { - File f = new File(s); - if (!f.exists() || !f.canExecute()) { + Path f = Path.of(s); + if (!Files.exists(f) || !Files.isExecutable(f)) { return false; } } diff --git a/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacPkgBundler.java b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacPkgBundler.java index 040469fec49..9662936b7b4 100644 --- a/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacPkgBundler.java +++ b/src/jdk.incubator.jpackage/macosx/classes/jdk/incubator/jpackage/internal/MacPkgBundler.java @@ -25,7 +25,6 @@ package jdk.incubator.jpackage.internal; -import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.net.URI; @@ -64,30 +63,38 @@ public class MacPkgBundler extends MacBaseInstallerBundler { private static final String TEMPLATE_POSTINSTALL_SCRIPT = "postinstall.template"; - private static final BundlerParamInfo PACKAGES_ROOT = + private static final BundlerParamInfo PACKAGES_ROOT = new StandardBundlerParam<>( "mac.pkg.packagesRoot", - File.class, + Path.class, params -> { - File packagesRoot = - new File(TEMP_ROOT.fetchFrom(params), "packages"); - packagesRoot.mkdirs(); + Path packagesRoot = + TEMP_ROOT.fetchFrom(params).resolve("packages"); + try { + Files.createDirectories(packagesRoot); + } catch (IOException ioe) { + return null; + } return packagesRoot; }, - (s, p) -> new File(s)); + (s, p) -> Path.of(s)); - protected final BundlerParamInfo SCRIPTS_DIR = + protected final BundlerParamInfo SCRIPTS_DIR = new StandardBundlerParam<>( "mac.pkg.scriptsDir", - File.class, + Path.class, params -> { - File scriptsDir = - new File(CONFIG_ROOT.fetchFrom(params), "scripts"); - scriptsDir.mkdirs(); + Path scriptsDir = + CONFIG_ROOT.fetchFrom(params).resolve("scripts"); + try { + Files.createDirectories(scriptsDir); + } catch (IOException ioe) { + return null; + } return scriptsDir; }, - (s, p) -> new File(s)); + (s, p) -> Path.of(s)); public static final BundlerParamInfo DEVELOPER_ID_INSTALLER_SIGNING_KEY = @@ -121,23 +128,23 @@ public class MacPkgBundler extends MacBaseInstallerBundler { params -> "", (s, p) -> s); - public File bundle(Map params, - File outdir) throws PackagerException { + public Path bundle(Map params, + Path outdir) throws PackagerException { Log.verbose(MessageFormat.format(I18N.getString("message.building-pkg"), APP_NAME.fetchFrom(params))); - IOUtils.writableOutputDir(outdir.toPath()); + IOUtils.writableOutputDir(outdir); try { - File appImageDir = prepareAppBundle(params); + Path appImageDir = prepareAppBundle(params); if (appImageDir != null && prepareConfigFiles(params)) { - File configScript = getConfig_Script(params); - if (configScript.exists()) { + Path configScript = getConfig_Script(params); + if (IOUtils.exists(configScript)) { Log.verbose(MessageFormat.format(I18N.getString( "message.running-script"), - configScript.getAbsolutePath())); + configScript.toAbsolutePath().toString())); IOUtils.run("bash", configScript); } @@ -150,33 +157,33 @@ public File bundle(Map params, } } - private File getPackages_AppPackage(Map params) { - return new File(PACKAGES_ROOT.fetchFrom(params), + private Path getPackages_AppPackage(Map params) { + return PACKAGES_ROOT.fetchFrom(params).resolve( APP_NAME.fetchFrom(params) + "-app.pkg"); } - private File getConfig_DistributionXMLFile( + private Path getConfig_DistributionXMLFile( Map params) { - return new File(CONFIG_ROOT.fetchFrom(params), "distribution.dist"); + return CONFIG_ROOT.fetchFrom(params).resolve("distribution.dist"); } - private File getConfig_BackgroundImage(Map params) { - return new File(CONFIG_ROOT.fetchFrom(params), + private Path getConfig_BackgroundImage(Map params) { + return CONFIG_ROOT.fetchFrom(params).resolve( APP_NAME.fetchFrom(params) + "-background.png"); } - private File getConfig_BackgroundImageDarkAqua(Map params) { - return new File(CONFIG_ROOT.fetchFrom(params), + private Path getConfig_BackgroundImageDarkAqua(Map params) { + return CONFIG_ROOT.fetchFrom(params).resolve( APP_NAME.fetchFrom(params) + "-background-darkAqua.png"); } - private File getScripts_PreinstallFile(Map params) { - return new File(SCRIPTS_DIR.fetchFrom(params), "preinstall"); + private Path getScripts_PreinstallFile(Map params) { + return SCRIPTS_DIR.fetchFrom(params).resolve("preinstall"); } - private File getScripts_PostinstallFile( + private Path getScripts_PostinstallFile( Map params) { - return new File(SCRIPTS_DIR.fetchFrom(params), "postinstall"); + return SCRIPTS_DIR.fetchFrom(params).resolve("postinstall"); } private String getAppIdentifier(Map params) { @@ -199,13 +206,13 @@ private void preparePackageScripts(Map params) .setCategory(I18N.getString("resource.pkg-preinstall-script")) .setSubstitutionData(data) .saveToFile(getScripts_PreinstallFile(params)); - getScripts_PreinstallFile(params).setExecutable(true, false); + getScripts_PreinstallFile(params).toFile().setExecutable(true, false); createResource(TEMPLATE_POSTINSTALL_SCRIPT, params) .setCategory(I18N.getString("resource.pkg-postinstall-script")) .setSubstitutionData(data) .saveToFile(getScripts_PostinstallFile(params)); - getScripts_PostinstallFile(params).setExecutable(true, false); + getScripts_PostinstallFile(params).toFile().setExecutable(true, false); } private static String URLEncoding(String pkgName) throws URISyntaxException { @@ -215,12 +222,12 @@ private static String URLEncoding(String pkgName) throws URISyntaxException { private void prepareDistributionXMLFile(Map params) throws IOException { - File f = getConfig_DistributionXMLFile(params); + Path f = getConfig_DistributionXMLFile(params); Log.verbose(MessageFormat.format(I18N.getString( - "message.preparing-distribution-dist"), f.getAbsolutePath())); + "message.preparing-distribution-dist"), f.toAbsolutePath().toString())); - IOUtils.createXml(f.toPath(), xml -> { + IOUtils.createXml(f, xml -> { xml.writeStartElement("installer-gui-script"); xml.writeAttribute("minSpecVersion", "1"); @@ -229,14 +236,16 @@ private void prepareDistributionXMLFile(Map params) xml.writeEndElement(); xml.writeStartElement("background"); - xml.writeAttribute("file", getConfig_BackgroundImage(params).getName()); + xml.writeAttribute("file", + getConfig_BackgroundImage(params).getFileName().toString()); xml.writeAttribute("mime-type", "image/png"); xml.writeAttribute("alignment", "bottomleft"); xml.writeAttribute("scaling", "none"); xml.writeEndElement(); xml.writeStartElement("background-darkAqua"); - xml.writeAttribute("file", getConfig_BackgroundImageDarkAqua(params).getName()); + xml.writeAttribute("file", + getConfig_BackgroundImageDarkAqua(params).getFileName().toString()); xml.writeAttribute("mime-type", "image/png"); xml.writeAttribute("alignment", "bottomleft"); xml.writeAttribute("scaling", "none"); @@ -244,9 +253,9 @@ private void prepareDistributionXMLFile(Map params) String licFileStr = LICENSE_FILE.fetchFrom(params); if (licFileStr != null) { - File licFile = new File(licFileStr); + Path licFile = Path.of(licFileStr); xml.writeStartElement("license"); - xml.writeAttribute("file", licFile.getAbsolutePath()); + xml.writeAttribute("file", licFile.toAbsolutePath().toString()); xml.writeAttribute("mime-type", "text/rtf"); xml.writeEndElement(); } @@ -288,7 +297,7 @@ private void prepareDistributionXMLFile(Map params) xml.writeAttribute("onConclusion", "none"); try { xml.writeCharacters(URLEncoding( - getPackages_AppPackage(params).getName())); + getPackages_AppPackage(params).getFileName().toString())); } catch (URISyntaxException ex) { throw new IOException(ex); } @@ -319,16 +328,15 @@ private boolean prepareConfigFiles(Map params) } // name of post-image script - private File getConfig_Script(Map params) { - return new File(CONFIG_ROOT.fetchFrom(params), + private Path getConfig_Script(Map params) { + return CONFIG_ROOT.fetchFrom(params).resolve( APP_NAME.fetchFrom(params) + "-post-image.sh"); } - private void patchCPLFile(File cpl) throws IOException { - String cplData = Files.readString(cpl.toPath()); + private void patchCPLFile(Path cpl) throws IOException { + String cplData = Files.readString(cpl); String[] lines = cplData.split("\n"); - try (PrintWriter out = new PrintWriter(Files.newBufferedWriter( - cpl.toPath()))) { + try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(cpl))) { int skip = 0; // Used to skip Java.runtime bundle, since // pkgbuild with --root will find two bundles app and Java runtime. @@ -360,35 +368,34 @@ private void patchCPLFile(File cpl) throws IOException { // So easy aproach will be to copy user provided app-image into temp folder // if root path contains other files. private String getRoot(Map params, - File appLocation) throws IOException { - String root = appLocation.getParent() == null ? - "." : appLocation.getParent(); - File rootDir = new File(root); + Path appLocation) throws IOException { + Path rootDir = appLocation.getParent() == null ? + Path.of(".") : appLocation.getParent(); - File[] list = rootDir.listFiles(); + Path[] list = Files.list(rootDir).toArray(Path[]::new); if (list != null) { // Should not happend // We should only have app image and/or .DS_Store if (list.length == 1) { - return root; + return rootDir.toString(); } else if (list.length == 2) { // Check case with app image and .DS_Store if (list[0].toString().toLowerCase().endsWith(".ds_store") || list[1].toString().toLowerCase().endsWith(".ds_store")) { - return root; // Only app image and .DS_Store + return rootDir.toString(); // Only app image and .DS_Store } } } // Copy to new root Path newRoot = Files.createTempDirectory( - TEMP_ROOT.fetchFrom(params).toPath(), "root-"); + TEMP_ROOT.fetchFrom(params), "root-"); Path source, dest; if (StandardBundlerParam.isRuntimeInstaller(params)) { // firs, is this already a runtime with // /Contents/Home - if so we need the Home dir - Path original = appLocation.toPath(); + Path original = appLocation; Path home = original.resolve("Contents/Home"); source = (Files.exists(home)) ? home : original; @@ -396,32 +403,31 @@ private String getRoot(Map params, dest = newRoot.resolve( MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params) + "/Contents/Home"); } else { - source = appLocation.toPath(); - dest = newRoot.resolve(appLocation.getName()); + source = appLocation; + dest = newRoot.resolve(appLocation.getFileName()); } IOUtils.copyRecursive(source, dest); return newRoot.toString(); } - private File createPKG(Map params, - File outdir, File appLocation) { + private Path createPKG(Map params, + Path outdir, Path appLocation) { // generic find attempt try { - File appPKG = getPackages_AppPackage(params); + Path appPKG = getPackages_AppPackage(params); String root = getRoot(params, appLocation); // Generate default CPL file - File cpl = new File(CONFIG_ROOT.fetchFrom(params).getAbsolutePath() - + File.separator + "cpl.plist"); + Path cpl = CONFIG_ROOT.fetchFrom(params).resolve("cpl.plist"); ProcessBuilder pb = new ProcessBuilder("pkgbuild", "--root", root, "--install-location", getInstallDir(params), "--analyze", - cpl.getAbsolutePath()); + cpl.toAbsolutePath().toString()); IOUtils.exec(pb); @@ -436,25 +442,25 @@ private File createPKG(Map params, "--install-location", getInstallDir(params), "--component-plist", - cpl.getAbsolutePath(), + cpl.toAbsolutePath().toString(), "--scripts", - SCRIPTS_DIR.fetchFrom(params).getAbsolutePath(), + SCRIPTS_DIR.fetchFrom(params).toAbsolutePath().toString(), "--identifier", MAC_CF_BUNDLE_IDENTIFIER.fetchFrom(params), - appPKG.getAbsolutePath()); + appPKG.toAbsolutePath().toString()); IOUtils.exec(pb); // build final package - File finalPKG = new File(outdir, INSTALLER_NAME.fetchFrom(params) + Path finalPKG = outdir.resolve(INSTALLER_NAME.fetchFrom(params) + INSTALLER_SUFFIX.fetchFrom(params) + ".pkg"); - outdir.mkdirs(); + Files.createDirectories(outdir); List commandLine = new ArrayList<>(); commandLine.add("productbuild"); commandLine.add("--resources"); - commandLine.add(CONFIG_ROOT.fetchFrom(params).getAbsolutePath()); + commandLine.add(CONFIG_ROOT.fetchFrom(params).toAbsolutePath().toString()); // maybe sign if (Optional.ofNullable(MacAppImageBuilder. @@ -482,11 +488,11 @@ private File createPKG(Map params, commandLine.add("--distribution"); commandLine.add( - getConfig_DistributionXMLFile(params).getAbsolutePath()); + getConfig_DistributionXMLFile(params).toAbsolutePath().toString()); commandLine.add("--package-path"); - commandLine.add(PACKAGES_ROOT.fetchFrom(params).getAbsolutePath()); + commandLine.add(PACKAGES_ROOT.fetchFrom(params).toAbsolutePath().toString()); - commandLine.add(finalPKG.getAbsolutePath()); + commandLine.add(finalPKG.toAbsolutePath().toString()); pb = new ProcessBuilder(commandLine); IOUtils.exec(pb); @@ -577,8 +583,8 @@ public boolean validate(Map params) } @Override - public File execute(Map params, - File outputParentDir) throws PackagerException { + public Path execute(Map params, + Path outputParentDir) throws PackagerException { return bundle(params, outputParentDir); } diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractAppImageBuilder.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractAppImageBuilder.java index 38dfe2a0660..a941c66d721 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractAppImageBuilder.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractAppImageBuilder.java @@ -25,7 +25,6 @@ package jdk.incubator.jpackage.internal; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; @@ -79,7 +78,7 @@ protected void copyApplication(Map params) } public static OverridableResource createIconResource(String defaultIconName, - BundlerParamInfo iconParam, Map params, + BundlerParamInfo iconParam, Map params, Map mainParams) throws IOException { if (mainParams != null) { @@ -119,12 +118,12 @@ public static OverridableResource createIconResource(String defaultIconName, private enum IconType { DefaultOrResourceDirIcon, CustomIcon, NoIcon }; private static IconType getLauncherIconType(Map params) { - File launcherIcon = ICON.fetchFrom(params); + Path launcherIcon = ICON.fetchFrom(params); if (launcherIcon == null) { return IconType.DefaultOrResourceDirIcon; } - if (launcherIcon.getName().isEmpty()) { + if (launcherIcon.toFile().getName().isEmpty()) { return IconType.NoIcon; } diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractBundler.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractBundler.java index 742d306e536..ef2ed7433ba 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractBundler.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AbstractBundler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,8 @@ package jdk.incubator.jpackage.internal; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.Map; @@ -39,12 +39,12 @@ */ abstract class AbstractBundler implements Bundler { - static final BundlerParamInfo IMAGES_ROOT = + static final BundlerParamInfo IMAGES_ROOT = new StandardBundlerParam<>( "imagesRoot", - File.class, - params -> new File( - StandardBundlerParam.TEMP_ROOT.fetchFrom(params), "images"), + Path.class, + params -> + StandardBundlerParam.TEMP_ROOT.fetchFrom(params).resolve("images"), (s, p) -> null); @Override diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AddLauncherArguments.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AddLauncherArguments.java index 5b2016348a7..79e3689a734 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AddLauncherArguments.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AddLauncherArguments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,9 @@ package jdk.incubator.jpackage.internal; +import java.nio.file.Path; import java.util.HashMap; import java.util.Map; -import java.io.File; import java.util.List; import jdk.incubator.jpackage.internal.Arguments.CLIOptions; @@ -116,7 +116,7 @@ private void initLauncherMap() { String value = getOptionValue(CLIOptions.ICON); Arguments.putUnlessNull(bundleParams, CLIOptions.ICON.getId(), - (value == null) ? null : new File(value)); + (value == null) ? null : Path.of(value)); // "arguments" and "java-options" even if value is null: if (allArgs.containsKey(CLIOptions.ARGUMENTS.getId())) { diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AppImageBundler.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AppImageBundler.java index 05dd5844647..56c0633bb07 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AppImageBundler.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AppImageBundler.java @@ -25,7 +25,6 @@ package jdk.incubator.jpackage.internal; -import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -82,14 +81,14 @@ final public boolean validate(Map params) } @Override - final public File execute(Map params, - File outputParentDir) throws PackagerException { + final public Path execute(Map params, + Path outputParentDir) throws PackagerException { if (StandardBundlerParam.isRuntimeInstaller(params)) { return PREDEFINED_RUNTIME_IMAGE.fetchFrom(params); } try { - return createAppBundle(params, outputParentDir.toPath()).toFile(); + return createAppBundle(params, outputParentDir); } catch (PackagerException pe) { throw pe; } catch (RuntimeException|IOException|ConfigException ex) { diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AppImageFile.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AppImageFile.java index 40ca3d5a3c8..94072561fa7 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AppImageFile.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/AppImageFile.java @@ -24,8 +24,8 @@ */ package jdk.incubator.jpackage.internal; -import java.io.FileInputStream; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -192,7 +192,7 @@ public static Document readXml(Path appImageDir) throws IOException { "http://apache.org/xml/features/nonvalidating/load-external-dtd", false); DocumentBuilder b = dbf.newDocumentBuilder(); - return b.parse(new FileInputStream(path.toFile())); + return b.parse(Files.newInputStream(path)); } catch (ParserConfigurationException | SAXException ex) { // Let caller sort this out throw new IOException(ex); diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Arguments.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Arguments.java index 5ab14fcc58a..41011a75daa 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Arguments.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Arguments.java @@ -24,9 +24,10 @@ */ package jdk.incubator.jpackage.internal; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; +import java.io.Reader; +import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.text.MessageFormat; import java.util.ArrayList; @@ -89,7 +90,7 @@ public class Arguments { private List allOptions = null; private String input = null; - private String output = null; + private Path output = null; private boolean hasMainJar = false; private boolean hasMainClass = false; @@ -130,8 +131,8 @@ public Arguments(String[] args) { addLaunchers = new ArrayList<>(); - output = Paths.get("").toAbsolutePath().toString(); - deployParams.setOutput(new File(output)); + output = Paths.get("").toAbsolutePath(); + deployParams.setOutput(output); } // CLIOptions is public for DeployParamsTest @@ -146,8 +147,8 @@ public enum CLIOptions { }), OUTPUT ("dest", "d", OptionCategories.PROPERTY, () -> { - context().output = popArg(); - context().deployParams.setOutput(new File(context().output)); + context().output = Path.of(popArg()); + context().deployParams.setOutput(context().output); }), DESCRIPTION ("description", OptionCategories.PROPERTY), @@ -670,7 +671,7 @@ private void generateBundle(Map params) Map localParams = new HashMap<>(params); try { bundler.validate(localParams); - File result = bundler.execute(localParams, deployParams.outdir); + Path result = bundler.execute(localParams, deployParams.outdir); if (result == null) { throw new PackagerException("MSG_BundlerFailed", bundler.getID(), bundler.getName()); @@ -696,7 +697,7 @@ private void generateBundle(Map params) if (userProvidedBuildRoot) { Log.verbose(MessageFormat.format( I18N.getString("message.debug-working-directory"), - (new File(buildRoot)).getAbsolutePath())); + (Path.of(buildRoot)).toAbsolutePath().toString())); } else { // always clean up the temporary directory created // when --temp option not used. @@ -716,10 +717,9 @@ static CLIOptions toCLIOption(String arg) { static Map getPropertiesFromFile(String filename) { Map map = new HashMap<>(); // load properties file - File file = new File(filename); Properties properties = new Properties(); - try (FileInputStream in = new FileInputStream(file)) { - properties.load(in); + try (Reader reader = Files.newBufferedReader(Path.of(filename))) { + properties.load(reader); } catch (IOException e) { Log.error("Exception: " + e.getMessage()); } @@ -808,11 +808,11 @@ private String getMainClassFromManifest() { JarFile jf; try { - File file = new File(input, mainJarPath); - if (!file.exists()) { + Path file = Path.of(input, mainJarPath); + if (!Files.exists(file)) { return null; } - jf = new JarFile(file); + jf = new JarFile(file.toFile()); Manifest m = jf.getManifest(); Attributes attrs = (m != null) ? m.getMainAttributes() : null; if (attrs != null) { diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/BundleParams.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/BundleParams.java index bc735fafefd..de56acc110b 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/BundleParams.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/BundleParams.java @@ -25,7 +25,6 @@ package jdk.incubator.jpackage.internal; - import java.util.HashMap; import java.util.Map; import static jdk.incubator.jpackage.internal.StandardBundlerParam.APP_NAME; diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Bundler.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Bundler.java index 06df6b3a10b..be702f711ea 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Bundler.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Bundler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ package jdk.incubator.jpackage.internal; -import java.io.File; +import java.nio.file.Path; import java.util.Map; /** @@ -104,8 +104,8 @@ public boolean validate(Map params) * forward slashes. * */ - public File execute(Map params, - File outputParentDir) throws PackagerException; + public Path execute(Map params, + Path outputParentDir) throws PackagerException; /** * Removes temporary files that are used for bundling. diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/DeployParams.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/DeployParams.java index 5f43b93a7fe..21ea8eea07c 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/DeployParams.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/DeployParams.java @@ -26,6 +26,7 @@ package jdk.incubator.jpackage.internal; import java.io.File; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.InvalidPathException; @@ -37,6 +38,8 @@ import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * DeployParams @@ -48,20 +51,20 @@ public class DeployParams { String targetFormat = null; // means default type for this platform - File outdir = null; + Path outdir = null; // raw arguments to the bundler Map bundlerArguments = new LinkedHashMap<>(); - public void setOutput(File output) { + public void setOutput(Path output) { outdir = output; } static class Template { - File in; - File out; + Path in; + Path out; - Template(File in, File out) { + Template(Path in, Path out) { this.in = in; this.out = out; } @@ -72,15 +75,19 @@ static class Template { // we may get "." as filename and assumption is we include // everything in the given folder // (IOUtils.copyfiles() have recursive behavior) - List expandFileset(File root) { - List files = new LinkedList<>(); - if (!Files.isSymbolicLink(root.toPath())) { - if (root.isDirectory()) { - File[] children = root.listFiles(); - if (children != null && children.length > 0) { - for (File f : children) { - files.addAll(expandFileset(f)); - } + List expandFileset(Path root) throws IOException { + List files = new LinkedList<>(); + if (!Files.isSymbolicLink(root)) { + if (Files.isDirectory(root)) { + List children = Files.list(root).collect(Collectors.toList()); + if (children != null && children.size() > 0) { + children.forEach(f -> { + try { + files.addAll(expandFileset(f)); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + }); } else { // Include empty folders files.add(root); @@ -110,7 +117,7 @@ static void validateName(String s, boolean forApp) } try { // name must be valid path element for this file system - Path p = (new File(s)).toPath(); + Path p = Path.of(s); // and it must be a single name element in a path if (p.getNameCount() != 1) { throw new PackagerException(exceptionKey, s); @@ -198,8 +205,8 @@ public void validate() throws PackagerException { String appImage = (String)bundlerArguments.get( Arguments.CLIOptions.PREDEFINED_APP_IMAGE.getId()); if (appImage != null) { - File appImageDir = new File(appImage); - if (!appImageDir.exists() || appImageDir.list().length == 0) { + Path appImageDir = Path.of(appImage); + if (!Files.exists(appImageDir) || appImageDir.toFile().list().length == 0) { throw new PackagerException("ERR_AppImageNotExist", appImage); } } @@ -208,10 +215,15 @@ public void validate() throws PackagerException { String root = (String)bundlerArguments.get( Arguments.CLIOptions.TEMP_ROOT.getId()); if (root != null) { - String [] contents = (new File(root)).list(); + try { + String [] contents = Files.list(Path.of(root)) + .toArray(String[]::new); - if (contents != null && contents.length > 0) { - throw new PackagerException("ERR_BuildRootInvalid", root); + if (contents != null && contents.length > 0) { + throw new PackagerException("ERR_BuildRootInvalid", root); + } + } catch (IOException ioe) { + throw new PackagerException(ioe); } } @@ -219,7 +231,7 @@ public void validate() throws PackagerException { String resources = (String)bundlerArguments.get( Arguments.CLIOptions.RESOURCE_DIR.getId()); if (resources != null) { - if (!(new File(resources)).exists()) { + if (!(Files.exists(Path.of(resources)))) { throw new PackagerException( "message.resource-dir-does-not-exist", Arguments.CLIOptions.RESOURCE_DIR.getId(), resources); @@ -230,7 +242,7 @@ public void validate() throws PackagerException { String runtime = (String)bundlerArguments.get( Arguments.CLIOptions.PREDEFINED_RUNTIME_IMAGE.getId()); if (runtime != null) { - if (!(new File(runtime)).exists()) { + if (!(Files.exists(Path.of(runtime)))) { throw new PackagerException( "message.runtime-image-dir-does-not-exist", Arguments.CLIOptions.PREDEFINED_RUNTIME_IMAGE.getId(), @@ -243,8 +255,7 @@ public void validate() throws PackagerException { String license = (String)bundlerArguments.get( Arguments.CLIOptions.LICENSE_FILE.getId()); if (license != null) { - File licenseFile = new File(license); - if (!licenseFile.exists()) { + if (!(Files.exists(Path.of(license)))) { throw new PackagerException("ERR_LicenseFileNotExit"); } } @@ -253,10 +264,9 @@ public void validate() throws PackagerException { String icon = (String)bundlerArguments.get( Arguments.CLIOptions.ICON.getId()); if (icon != null) { - File iconFile = new File(icon); - if (!iconFile.exists()) { + if (!(Files.exists(Path.of(icon)))) { throw new PackagerException("ERR_IconFileNotExit", - iconFile.getAbsolutePath()); + Path.of(icon).toAbsolutePath().toString()); } } } diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Executor.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Executor.java index d9b2b7f652c..649756ac9a8 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Executor.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/Executor.java @@ -25,10 +25,10 @@ package jdk.incubator.jpackage.internal; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; @@ -82,12 +82,12 @@ int execute() throws IOException { output = null; boolean needProcessOutput = outputConsumer != null || Log.isVerbose() || saveOutput; - File outputFile = null; + Path outputFile = null; if (needProcessOutput) { pb.redirectErrorStream(true); if (writeOutputToFile) { - outputFile = File.createTempFile("jpackageOutputTempFile", ".tmp"); - pb.redirectOutput(outputFile); + outputFile = Files.createTempFile("jpackageOutputTempFile", ".tmp"); + pb.redirectOutput(outputFile.toFile()); } } else { // We are not going to read process output, so need to notify @@ -115,8 +115,8 @@ int execute() throws IOException { Supplier> outputStream; if (writeOutputToFile) { - savedOutput = Files.readAllLines(outputFile.toPath()); - outputFile.delete(); + savedOutput = Files.readAllLines(outputFile); + Files.delete(outputFile); outputStream = () -> { if (savedOutput != null) { return savedOutput.stream(); diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/FileAssociation.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/FileAssociation.java index 800ec2a46f8..9c4887e590e 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/FileAssociation.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/FileAssociation.java @@ -25,7 +25,6 @@ package jdk.incubator.jpackage.internal; -import java.io.File; import java.nio.file.Path; import java.text.MessageFormat; import java.util.Collections; @@ -86,9 +85,9 @@ static List fetchFrom(Map params) { assoc.mimeTypes = Optional.ofNullable( FA_CONTENT_TYPE.fetchFrom(fa)).orElse(Collections.emptyList()); - File icon = FA_ICON.fetchFrom(fa); + Path icon = FA_ICON.fetchFrom(fa); if (icon != null) { - assoc.iconPath = icon.toPath(); + assoc.iconPath = icon; } return assoc; diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/IOUtils.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/IOUtils.java index fa31d485dfd..0e533ad588e 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/IOUtils.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/IOUtils.java @@ -28,7 +28,6 @@ import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; -import java.io.File; import java.io.PrintStream; import java.io.Writer; import java.lang.reflect.InvocationHandler; @@ -56,11 +55,11 @@ */ public class IOUtils { - public static void deleteRecursive(File path) throws IOException { - if (!path.exists()) { + public static void deleteRecursive(Path directory) throws IOException { + if (!Files.exists(directory)) { return; } - Path directory = path.toPath(); + Files.walkFileTree(directory, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path file, @@ -119,22 +118,30 @@ public FileVisitResult visitFile(final Path file, }); } - public static void copyFile(File sourceFile, File destFile) + public static void copyFile(Path sourceFile, Path destFile) throws IOException { - Files.createDirectories(destFile.getParentFile().toPath()); + Files.createDirectories(destFile.getParent()); - Files.copy(sourceFile.toPath(), destFile.toPath(), + Files.copy(sourceFile, destFile, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES); } + public static boolean exists(Path path) { + if (path == null) { + return false; + } + + return Files.exists(path); + } + // run "launcher paramfile" in the directory where paramfile is kept - public static void run(String launcher, File paramFile) + public static void run(String launcher, Path paramFile) throws IOException { - if (paramFile != null && paramFile.exists()) { + if (IOUtils.exists(paramFile)) { ProcessBuilder pb = - new ProcessBuilder(launcher, paramFile.getName()); - pb = pb.directory(paramFile.getParentFile()); + new ProcessBuilder(launcher, paramFile.getFileName().toString()); + pb = pb.directory(paramFile.getParent().toFile()); exec(pb); } } @@ -222,15 +229,18 @@ public static int getProcessOutput(List result, String... args) } static void writableOutputDir(Path outdir) throws PackagerException { - File file = outdir.toFile(); - - if (!file.isDirectory() && !file.mkdirs()) { - throw new PackagerException("error.cannot-create-output-dir", - file.getAbsolutePath()); + if (!Files.isDirectory(outdir)) { + try { + Files.createDirectories(outdir); + } catch (IOException ex) { + throw new PackagerException("error.cannot-create-output-dir", + outdir.toAbsolutePath().toString()); + } } - if (!file.canWrite()) { + + if (!Files.isWritable(outdir)) { throw new PackagerException("error.cannot-write-to-output-dir", - file.getAbsolutePath()); + outdir.toAbsolutePath().toString()); } } diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/LauncherData.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/LauncherData.java index 752509444a9..ef9d36854f3 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/LauncherData.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/LauncherData.java @@ -145,7 +145,7 @@ private static LauncherData createModular(String mainModule, // Failed to find module in the specified module path list and // there is external runtime given to jpackage. // Lookup module in this runtime. - Path cookedRuntime = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params).toPath(); + Path cookedRuntime = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params); launcherData.moduleInfo = ModuleInfo.fromCookedRuntime(moduleName, cookedRuntime); } @@ -231,10 +231,11 @@ private void initClasspath(Map params) if (inputDir == null) { classPath = Collections.emptyList(); } else { - try (Stream walk = Files.walk(inputDir, 1)) { + try (Stream walk = Files.walk(inputDir, Integer.MAX_VALUE)) { Set jars = walk.filter(Files::isRegularFile) .filter(file -> file.toString().endsWith(".jar")) - .map(Path::getFileName) + .map(p -> inputDir.toAbsolutePath() + .relativize(p.toAbsolutePath())) .collect(Collectors.toSet()); jars.remove(mainJarName); classPath = jars.stream().sorted().collect(Collectors.toList()); @@ -292,7 +293,7 @@ private static List getModulePath(Map params) List modulePath = getPathListParameter(Arguments.CLIOptions.MODULE_PATH.getId(), params); if (params.containsKey(PREDEFINED_RUNTIME_IMAGE.getID())) { - Path runtimePath = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params).toPath(); + Path runtimePath = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params); runtimePath = runtimePath.resolve("lib"); modulePath = Stream.of(modulePath, List.of(runtimePath)) .flatMap(List::stream) diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/PathGroup.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/PathGroup.java index a791ed36293..d7e332f3fbf 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/PathGroup.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/PathGroup.java @@ -24,7 +24,6 @@ */ package jdk.incubator.jpackage.internal; -import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -200,7 +199,7 @@ public void createDirectory(Path dir) throws IOException { for (var action: entries) { Path src = action.getKey(); Path dst = action.getValue(); - if (src.toFile().isDirectory()) { + if (Files.isDirectory(src)) { try (Stream stream = Files.walk(src)) { stream.sequential().forEach(path -> actions.put(dst.resolve( src.relativize(path)).normalize(), path)); @@ -222,7 +221,7 @@ public void createDirectory(Path dir) throws IOException { continue; } - if (src.toFile().isDirectory()) { + if (Files.isDirectory(src)) { handler.createDirectory(dst); } else { handler.copyFile(src, dst); @@ -232,8 +231,8 @@ public void createDirectory(Path dir) throws IOException { if (move) { // Delete source dirs. for (var entry: entries) { - File srcFile = entry.getKey().toFile(); - if (srcFile.isDirectory()) { + Path srcFile = entry.getKey(); + if (Files.isDirectory(srcFile)) { IOUtils.deleteRecursive(srcFile); } } diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ScriptRunner.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ScriptRunner.java index a2a140640ce..9d6f037b400 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ScriptRunner.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/ScriptRunner.java @@ -76,7 +76,7 @@ ScriptRunner setEnvironmentVariable(String envVarName, String envVarValue) { public void run(Map params) throws IOException { String scriptName = String.format("%s-%s%s", APP_NAME.fetchFrom(params), scriptNameSuffix, scriptSuffix()); - Path scriptPath = CONFIG_ROOT.fetchFrom(params).toPath().resolve( + Path scriptPath = CONFIG_ROOT.fetchFrom(params).resolve( scriptName); createResource(null, params) .setCategory(I18N.getString(resourceCategoryId)) diff --git a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/StandardBundlerParam.java b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/StandardBundlerParam.java index 1ea0eb08c32..a6e29cae34b 100644 --- a/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/StandardBundlerParam.java +++ b/src/jdk.incubator.jpackage/share/classes/jdk/incubator/jpackage/internal/StandardBundlerParam.java @@ -120,12 +120,12 @@ (s, p) -> s ); - static final StandardBundlerParam PREDEFINED_RUNTIME_IMAGE = + static final StandardBundlerParam PREDEFINED_RUNTIME_IMAGE = new StandardBundlerParam<>( Arguments.CLIOptions.PREDEFINED_RUNTIME_IMAGE.getId(), - File.class, + Path.class, params -> null, - (s, p) -> new File(s) + (s, p) -> Path.of(s) ); static final StandardBundlerParam APP_NAME = @@ -141,9 +141,9 @@ } return s; } else if (isRuntimeInstaller(params)) { - File f = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params); + Path f = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params); if (f != null) { - return f.getName(); + return f.getFileName().toString(); } } return null; @@ -151,12 +151,12 @@ (s, p) -> s ); - static final StandardBundlerParam ICON = + static final StandardBundlerParam ICON = new StandardBundlerParam<>( Arguments.CLIOptions.ICON.getId(), - File.class, + Path.class, params -> null, - (s, p) -> new File(s) + (s, p) -> Path.of(s) ); static final StandardBundlerParam VENDOR = @@ -229,29 +229,31 @@ (s, p) -> s ); - static final StandardBundlerParam TEMP_ROOT = + static final StandardBundlerParam TEMP_ROOT = new StandardBundlerParam<>( Arguments.CLIOptions.TEMP_ROOT.getId(), - File.class, + Path.class, params -> { try { - return Files.createTempDirectory( - "jdk.incubator.jpackage").toFile(); + return Files.createTempDirectory("jdk.incubator.jpackage"); } catch (IOException ioe) { return null; } }, - (s, p) -> new File(s) + (s, p) -> Path.of(s) ); - public static final StandardBundlerParam CONFIG_ROOT = + public static final StandardBundlerParam CONFIG_ROOT = new StandardBundlerParam<>( "configRoot", - File.class, + Path.class, params -> { - File root = - new File(TEMP_ROOT.fetchFrom(params), "config"); - root.mkdirs(); + Path root = TEMP_ROOT.fetchFrom(params).resolve("config"); + try { + Files.createDirectories(root); + } catch (IOException ioe) { + return null; + } return root; }, (s, p) -> null @@ -277,12 +279,12 @@ true : Boolean.valueOf(s) ); - static final StandardBundlerParam RESOURCE_DIR = + static final StandardBundlerParam RESOURCE_DIR = new StandardBundlerParam<>( Arguments.CLIOptions.RESOURCE_DIR.getId(), - File.class, + Path.class, params -> null, - (s, p) -> new File(s) + (s, p) -> Path.of(s) ); static final BundlerParamInfo INSTALL_DIR = @@ -293,12 +295,12 @@ (s, p) -> s ); - static final StandardBundlerParam PREDEFINED_APP_IMAGE = + static final StandardBundlerParam PREDEFINED_APP_IMAGE = new StandardBundlerParam<>( Arguments.CLIOptions.PREDEFINED_APP_IMAGE.getId(), - File.class, + Path.class, params -> null, - (s, p) -> new File(s)); + (s, p) -> Path.of(s)); @SuppressWarnings("unchecked") static final StandardBundlerParam>> ADD_LAUNCHERS = @@ -346,16 +348,16 @@ new StandardBundlerParam<>( "fileAssociation.description", String.class, - params -> APP_NAME.fetchFrom(params) + " File", + params -> APP_NAME.fetchFrom(params) + " Path", null ); - static final StandardBundlerParam FA_ICON = + static final StandardBundlerParam FA_ICON = new StandardBundlerParam<>( "fileAssociation.icon", - File.class, + Path.class, ICON::fetchFrom, - (s, p) -> new File(s) + (s, p) -> Path.of(s) ); @SuppressWarnings("unchecked") @@ -449,9 +451,9 @@ static boolean isRuntimeInstaller(Map params) { return params.containsKey(PREDEFINED_RUNTIME_IMAGE.getID()); } - static File getPredefinedAppImage(Map params) { - File applicationImage = PREDEFINED_APP_IMAGE.fetchFrom(params); - if (applicationImage != null && !applicationImage.exists()) { + static Path getPredefinedAppImage(Map params) { + Path applicationImage = PREDEFINED_APP_IMAGE.fetchFrom(params); + if (applicationImage != null && !IOUtils.exists(applicationImage)) { throw new RuntimeException( MessageFormat.format(I18N.getString( "message.app-image-dir-does-not-exist"), @@ -463,8 +465,8 @@ static File getPredefinedAppImage(Map params) { static void copyPredefinedRuntimeImage(Map params, ApplicationLayout appLayout) throws IOException, ConfigException { - File topImage = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params); - if (!topImage.exists()) { + Path topImage = PREDEFINED_RUNTIME_IMAGE.fetchFrom(params); + if (!IOUtils.exists(topImage)) { throw new ConfigException( MessageFormat.format(I18N.getString( "message.runtime-image-dir-does-not-exist"), @@ -477,17 +479,17 @@ static void copyPredefinedRuntimeImage(Map params, if (Platform.isMac()) { // On Mac topImage can be runtime root or runtime home. - Path runtimeHome = topImage.toPath().resolve("Contents/Home"); + Path runtimeHome = topImage.resolve("Contents/Home"); if (Files.isDirectory(runtimeHome)) { // topImage references runtime root, adjust it to pick data from // runtime home - topImage = runtimeHome.toFile(); + topImage = runtimeHome; } } // copy whole runtime, need to skip jmods and src.zip final List excludes = Arrays.asList("jmods", "src.zip"); - IOUtils.copyRecursive(topImage.toPath(), + IOUtils.copyRecursive(topImage, appLayout.runtimeHomeDirectory(), excludes); // if module-path given - copy modules to appDir/mods diff --git a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/ExecutableRebrander.java b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/ExecutableRebrander.java index 86b07d2752f..53af7209d4d 100644 --- a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/ExecutableRebrander.java +++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/ExecutableRebrander.java @@ -108,7 +108,8 @@ ExecutableRebrander addAction(UpdateResourceAction action) { private void rebrandExecutable(Map params, Path target, UpdateResourceAction action) throws IOException { try { - String tempDirectory = TEMP_ROOT.fetchFrom(params).getAbsolutePath(); + String tempDirectory = TEMP_ROOT.fetchFrom(params) + .toAbsolutePath().toString(); if (WindowsDefender.isThereAPotentialWindowsDefenderIssue( tempDirectory)) { Log.verbose(MessageFormat.format(I18N.getString( diff --git a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinExeBundler.java b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinExeBundler.java index cb7e8e26dff..b72cf6d1164 100644 --- a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinExeBundler.java +++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinExeBundler.java @@ -24,12 +24,10 @@ */ package jdk.incubator.jpackage.internal; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.text.MessageFormat; import java.util.Map; @@ -39,16 +37,20 @@ public class WinExeBundler extends AbstractBundler { System.loadLibrary("jpackage"); } - public static final BundlerParamInfo EXE_IMAGE_DIR + public static final BundlerParamInfo EXE_IMAGE_DIR = new StandardBundlerParam<>( "win.exe.imageDir", - File.class, + Path.class, params -> { - File imagesRoot = IMAGES_ROOT.fetchFrom(params); - if (!imagesRoot.exists()) { - imagesRoot.mkdirs(); + Path imagesRoot = IMAGES_ROOT.fetchFrom(params); + if (!Files.exists(imagesRoot)) { + try { + Files.createDirectories(imagesRoot); + } catch (IOException ioe) { + return null; + } } - return new File(imagesRoot, "win-exe.image"); + return imagesRoot.resolve("win-exe.image"); }, (s, p) -> null); @@ -70,8 +72,8 @@ public String getBundleType() { } @Override - public File execute(Map params, - File outputParentDir) throws PackagerException { + public Path execute(Map params, + Path outputParentDir) throws PackagerException { return bundle(params, outputParentDir); } @@ -91,22 +93,22 @@ public boolean validate(Map params) return msiBundler.validate(params); } - public File bundle(Map params, File outdir) + public Path bundle(Map params, Path outdir) throws PackagerException { - IOUtils.writableOutputDir(outdir.toPath()); + IOUtils.writableOutputDir(outdir); - File exeImageDir = EXE_IMAGE_DIR.fetchFrom(params); + Path exeImageDir = EXE_IMAGE_DIR.fetchFrom(params); // Write msi to temporary directory. - File msi = msiBundler.execute(params, exeImageDir); + Path msi = msiBundler.execute(params, exeImageDir); try { new ScriptRunner() - .setDirectory(msi.toPath().getParent()) + .setDirectory(msi.getParent()) .setResourceCategoryId("resource.post-msi-script") .setScriptNameSuffix("post-msi") - .setEnvironmentVariable("JpMsiFile", msi.getAbsolutePath().toString()) + .setEnvironmentVariable("JpMsiFile", msi.toAbsolutePath().toString()) .run(params); return buildEXE(params, msi, outdir); @@ -116,35 +118,34 @@ public File bundle(Map params, File outdir) } } - private File buildEXE(Map params, File msi, - File outdir) throws IOException { + private Path buildEXE(Map params, Path msi, + Path outdir) throws IOException { Log.verbose(MessageFormat.format( I18N.getString("message.outputting-to-location"), - outdir.getAbsolutePath())); + outdir.toAbsolutePath().toString())); // Copy template msi wrapper next to msi file - final Path exePath = IOUtils.replaceSuffix(msi.toPath(), ".exe"); + final Path exePath = IOUtils.replaceSuffix(msi, ".exe"); try (InputStream is = OverridableResource.readDefault(EXE_WRAPPER_NAME)) { Files.copy(is, exePath); } new ExecutableRebrander().addAction((resourceLock) -> { // Embed msi in msi wrapper exe. - embedMSI(resourceLock, msi.getAbsolutePath()); + embedMSI(resourceLock, msi.toAbsolutePath().toString()); }).rebrandInstaller(params, exePath); - Path dstExePath = Paths.get(outdir.getAbsolutePath(), - exePath.getFileName().toString()); + Path dstExePath = outdir.toAbsolutePath().resolve(exePath.getFileName()); Files.deleteIfExists(dstExePath); Files.copy(exePath, dstExePath); Log.verbose(MessageFormat.format( I18N.getString("message.output-location"), - outdir.getAbsolutePath())); + outdir.toAbsolutePath().toString())); - return dstExePath.toFile(); + return dstExePath; } private final WinMsiBundler msiBundler = new WinMsiBundler(); diff --git a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinMsiBundler.java b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinMsiBundler.java index 7a1791d7209..a1970546a09 100644 --- a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinMsiBundler.java +++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WinMsiBundler.java @@ -25,8 +25,6 @@ package jdk.incubator.jpackage.internal; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.Writer; @@ -101,21 +99,27 @@ */ public class WinMsiBundler extends AbstractBundler { - public static final BundlerParamInfo MSI_IMAGE_DIR = + public static final BundlerParamInfo MSI_IMAGE_DIR = new StandardBundlerParam<>( "win.msi.imageDir", - File.class, + Path.class, params -> { - File imagesRoot = IMAGES_ROOT.fetchFrom(params); - if (!imagesRoot.exists()) imagesRoot.mkdirs(); - return new File(imagesRoot, "win-msi.image"); + Path imagesRoot = IMAGES_ROOT.fetchFrom(params); + if (!Files.exists(imagesRoot)) { + try { + Files.createDirectories(imagesRoot); + } catch (IOException ioe) { + return null; + } + } + return imagesRoot.resolve("win-msi.image"); }, (s, p) -> null); - public static final BundlerParamInfo WIN_APP_IMAGE = + public static final BundlerParamInfo WIN_APP_IMAGE = new StandardBundlerParam<>( "win.app.image", - File.class, + Path.class, null, (s, p) -> null); @@ -284,15 +288,14 @@ public boolean validate(Map params) private void prepareProto(Map params) throws PackagerException, IOException { - File appImage = StandardBundlerParam.getPredefinedAppImage(params); - File appDir = null; + Path appImage = StandardBundlerParam.getPredefinedAppImage(params); + Path appDir; // we either have an application image or need to build one if (appImage != null) { - appDir = new File(MSI_IMAGE_DIR.fetchFrom(params), - APP_NAME.fetchFrom(params)); + appDir = MSI_IMAGE_DIR.fetchFrom(params).resolve(APP_NAME.fetchFrom(params)); // copy everything from appImage dir into appDir/name - IOUtils.copyRecursive(appImage.toPath(), appDir.toPath()); + IOUtils.copyRecursive(appImage, appDir); } else { appDir = appImageBundler.execute(params, MSI_IMAGE_DIR.fetchFrom( params)); @@ -305,12 +308,12 @@ private void prepareProto(Map params) // Ignore custom icon if any as we don't want to copy anything in // Java Runtime image. installerIcon = ApplicationLayout.javaRuntime() - .resolveAt(appDir.toPath()) + .resolveAt(appDir) .runtimeDirectory() .resolve(Path.of("bin", "java.exe")); } else { installerIcon = ApplicationLayout.windowsAppImage() - .resolveAt(appDir.toPath()) + .resolveAt(appDir) .launchersDirectory() .resolve(APP_NAME.fetchFrom(params) + ".exe"); } @@ -322,31 +325,31 @@ private void prepareProto(Map params) if (licenseFile != null) { // need to copy license file to the working directory // and convert to rtf if needed - File lfile = new File(licenseFile); - File destFile = new File(CONFIG_ROOT.fetchFrom(params), - lfile.getName()); + Path lfile = Path.of(licenseFile); + Path destFile = CONFIG_ROOT.fetchFrom(params) + .resolve(lfile.getFileName()); IOUtils.copyFile(lfile, destFile); - destFile.setWritable(true); + destFile.toFile().setWritable(true); ensureByMutationFileIsRTF(destFile); } } @Override - public File execute(Map params, - File outputParentDir) throws PackagerException { + public Path execute(Map params, + Path outputParentDir) throws PackagerException { - IOUtils.writableOutputDir(outputParentDir.toPath()); + IOUtils.writableOutputDir(outputParentDir); - Path imageDir = MSI_IMAGE_DIR.fetchFrom(params).toPath(); + Path imageDir = MSI_IMAGE_DIR.fetchFrom(params); try { Files.createDirectories(imageDir); prepareProto(params); wixSourcesBuilder - .initFromParams(WIN_APP_IMAGE.fetchFrom(params).toPath(), params) - .createMainFragment(CONFIG_ROOT.fetchFrom(params).toPath().resolve( + .initFromParams(WIN_APP_IMAGE.fetchFrom(params), params) + .createMainFragment(CONFIG_ROOT.fetchFrom(params).resolve( "bundle.wxf")); Map wixVars = prepareMainProjectFile(params); @@ -389,7 +392,7 @@ private Map prepareMainProjectFile( data.put("JpAppVersion", PRODUCT_VERSION.fetchFrom(params)); data.put("JpIcon", installerIcon.toString()); - final Path configDir = CONFIG_ROOT.fetchFrom(params).toPath(); + final Path configDir = CONFIG_ROOT.fetchFrom(params); data.put("JpConfigDir", configDir.toAbsolutePath().toString()); @@ -399,9 +402,9 @@ private Map prepareMainProjectFile( String licenseFile = LICENSE_FILE.fetchFrom(params); if (licenseFile != null) { - String lname = new File(licenseFile).getName(); - File destFile = new File(CONFIG_ROOT.fetchFrom(params), lname); - data.put("JpLicenseRtf", destFile.getAbsolutePath()); + String lname = Path.of(licenseFile).getFileName().toString(); + Path destFile = CONFIG_ROOT.fetchFrom(params).resolve(lname); + data.put("JpLicenseRtf", destFile.toAbsolutePath().toString()); } // Copy CA dll to include with installer @@ -409,9 +412,7 @@ private Map prepareMainProjectFile( data.put("JpInstallDirChooser", "yes"); String fname = "wixhelper.dll"; try (InputStream is = OverridableResource.readDefault(fname)) { - Files.copy(is, Paths.get( - CONFIG_ROOT.fetchFrom(params).getAbsolutePath(), - fname)); + Files.copy(is, CONFIG_ROOT.fetchFrom(params).resolve(fname)); } } @@ -419,9 +420,7 @@ private Map prepareMainProjectFile( for (String loc : Arrays.asList("en", "ja", "zh_CN")) { String fname = "MsiInstallerStrings_" + loc + ".wxl"; try (InputStream is = OverridableResource.readDefault(fname)) { - Files.copy(is, Paths.get( - CONFIG_ROOT.fetchFrom(params).getAbsolutePath(), - fname)); + Files.copy(is, CONFIG_ROOT.fetchFrom(params).resolve(fname)); } } @@ -436,28 +435,28 @@ private Map prepareMainProjectFile( return data; } - private File buildMSI(Map params, - Map wixVars, File outdir) + private Path buildMSI(Map params, + Map wixVars, Path outdir) throws IOException { - File msiOut = new File( - outdir, INSTALLER_FILE_NAME.fetchFrom(params) + ".msi"); + Path msiOut = outdir.resolve(INSTALLER_FILE_NAME.fetchFrom(params) + ".msi"); Log.verbose(MessageFormat.format(I18N.getString( - "message.preparing-msi-config"), msiOut.getAbsolutePath())); + "message.preparing-msi-config"), msiOut.toAbsolutePath() + .toString())); WixPipeline wixPipeline = new WixPipeline() .setToolset(wixToolset.entrySet().stream().collect( Collectors.toMap( entry -> entry.getKey(), entry -> entry.getValue().path))) - .setWixObjDir(TEMP_ROOT.fetchFrom(params).toPath().resolve("wixobj")) - .setWorkDir(WIN_APP_IMAGE.fetchFrom(params).toPath()) - .addSource(CONFIG_ROOT.fetchFrom(params).toPath().resolve("main.wxs"), wixVars) - .addSource(CONFIG_ROOT.fetchFrom(params).toPath().resolve("bundle.wxf"), null); + .setWixObjDir(TEMP_ROOT.fetchFrom(params).resolve("wixobj")) + .setWorkDir(WIN_APP_IMAGE.fetchFrom(params)) + .addSource(CONFIG_ROOT.fetchFrom(params).resolve("main.wxs"), wixVars) + .addSource(CONFIG_ROOT.fetchFrom(params).resolve("bundle.wxf"), null); Log.verbose(MessageFormat.format(I18N.getString( - "message.generating-msi"), msiOut.getAbsolutePath())); + "message.generating-msi"), msiOut.toAbsolutePath().toString())); boolean enableLicenseUI = (LICENSE_FILE.fetchFrom(params) != null); boolean enableInstalldirUI = INSTALLDIR_CHOOSER.fetchFrom(params); @@ -472,26 +471,27 @@ private File buildMSI(Map params, } wixPipeline.addLightOptions("-loc", - CONFIG_ROOT.fetchFrom(params).toPath().resolve(I18N.getString( + CONFIG_ROOT.fetchFrom(params).resolve(I18N.getString( "resource.wxl-file-name")).toAbsolutePath().toString()); // Only needed if we using CA dll, so Wix can find it if (enableInstalldirUI) { - wixPipeline.addLightOptions("-b", CONFIG_ROOT.fetchFrom(params).getAbsolutePath()); + wixPipeline.addLightOptions("-b", CONFIG_ROOT.fetchFrom(params) + .toAbsolutePath().toString()); } - wixPipeline.buildMsi(msiOut.toPath().toAbsolutePath()); + wixPipeline.buildMsi(msiOut.toAbsolutePath()); return msiOut; } - private static void ensureByMutationFileIsRTF(File f) { - if (f == null || !f.isFile()) return; + private static void ensureByMutationFileIsRTF(Path f) { + if (f == null || !Files.isRegularFile(f)) return; try { boolean existingLicenseIsRTF = false; - try (FileInputStream fin = new FileInputStream(f)) { + try (InputStream fin = Files.newInputStream(f)) { byte[] firstBits = new byte[7]; if (fin.read(firstBits) == firstBits.length) { @@ -501,9 +501,9 @@ private static void ensureByMutationFileIsRTF(File f) { } if (!existingLicenseIsRTF) { - List oldLicense = Files.readAllLines(f.toPath()); + List oldLicense = Files.readAllLines(f); try (Writer w = Files.newBufferedWriter( - f.toPath(), Charset.forName("Windows-1252"))) { + f, Charset.forName("Windows-1252"))) { w.write("{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033" + "{\\fonttbl{\\f0\\fnil\\fcharset0 Arial;}}\n" + "\\viewkind4\\uc1\\pard\\sa200\\sl276" diff --git a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsAppImageBuilder.java b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsAppImageBuilder.java index 28081c8ccef..cb34707d345 100644 --- a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsAppImageBuilder.java +++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsAppImageBuilder.java @@ -25,7 +25,6 @@ package jdk.incubator.jpackage.internal; -import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; @@ -45,20 +44,21 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder { private static final String TEMPLATE_APP_ICON ="java48.ico"; - public static final BundlerParamInfo ICON_ICO = + public static final BundlerParamInfo ICON_ICO = new StandardBundlerParam<>( "icon.ico", - File.class, + Path.class, params -> { - File f = ICON.fetchFrom(params); - if (f != null && !f.getName().toLowerCase().endsWith(".ico")) { + Path f = ICON.fetchFrom(params); + if (f != null && f.getFileName() != null && !f.getFileName() + .toString().toLowerCase().endsWith(".ico")) { Log.error(MessageFormat.format( I18N.getString("message.icon-not-ico"), f)); return null; } return f; }, - (s, p) -> new File(s)); + (s, p) -> Path.of(s)); public static final StandardBundlerParam CONSOLE_HINT = new StandardBundlerParam<>( diff --git a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixSourcesBuilder.java b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixSourcesBuilder.java index 5c018dd34a6..2193ef74054 100644 --- a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixSourcesBuilder.java +++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixSourcesBuilder.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Path; +import java.nio.file.Files; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; @@ -160,7 +161,7 @@ private void normalizeFileAssociation(FileAssociation fa) { fa.launcherPath = addExeSuffixToPath( installedAppImage.launchersDirectory().resolve(fa.launcherPath)); - if (fa.iconPath != null && !fa.iconPath.toFile().exists()) { + if (fa.iconPath != null && !Files.exists(fa.iconPath)) { fa.iconPath = null; } diff --git a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixTool.java b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixTool.java index de46437b897..cebe3936f8b 100644 --- a/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixTool.java +++ b/src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WixTool.java @@ -84,7 +84,7 @@ ToolInfo find() throws ConfigException { for (var dir : findWixInstallDirs()) { Path path = dir.resolve(toolFileName); - if (path.toFile().exists()) { + if (Files.exists(path)) { reason = createToolValidator(path, version).get(); if (reason != null) { throw reason; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HandleCleaner.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HandleCleaner.java index 1599bf13089..1a9b244c441 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HandleCleaner.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HandleCleaner.java @@ -65,8 +65,8 @@ void doCleanup() { CompilerToVM.compilerToVM().deleteGlobalHandle(handle); } else { // Setting the target of a jmetadata handle to 0 enables - // the handle to be reused. See MetadataHandleBlock in - // jvmciRuntime.cpp for more info. + // the handle to be reused. See MetadataHandles in + // metadataHandles.hpp for more info. long value = UNSAFE.getLong(null, handle); UNSAFE.compareAndSetLong(null, handle, value, 0); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index 45372555486..63f1e2c71f4 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collections; +import java.util.Formatter; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -218,6 +219,15 @@ static String callToString(Object o) { return o.toString(); } + /** + * Set of recognized {@code "jvmci.*"} system properties. Entries not associated with an + * {@link Option} have this object as their value. + */ + static final Map options = new HashMap<>(); + static { + options.put("jvmci.class.path.append", options); + } + /** * A list of all supported JVMCI options. */ @@ -236,7 +246,7 @@ public enum Option { TraceMethodDataFilter(String.class, null, "Enables tracing of profiling info when read by JVMCI.", "Empty value: trace all methods", - "Non-empty value: trace methods whose fully qualified name contains the value."), + "Non-empty value: trace methods whose fully qualified name contains the value."), UseProfilingInformation(Boolean.class, true, ""); // @formatter:on @@ -253,7 +263,7 @@ public enum Option { private final Class type; @NativeImageReinitialize private Object value; private final Object defaultValue; - private boolean isDefault; + private boolean isDefault = true; private final String[] helpLines; Option(Class type, Object defaultValue, String... helpLines) { @@ -261,27 +271,37 @@ public enum Option { this.type = type; this.defaultValue = defaultValue; this.helpLines = helpLines; + Object existing = options.put(getPropertyName(), this); + assert existing == null : getPropertyName(); } @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum") - private Object getValue() { - if (value == null) { - String propertyValue = Services.getSavedProperty(getPropertyName()); - if (propertyValue == null) { - this.value = defaultValue == null ? NULL_VALUE : defaultValue; - this.isDefault = true; + private void init(String propertyValue) { + assert value == null : "cannot re-initialize " + name(); + if (propertyValue == null) { + this.value = defaultValue == null ? NULL_VALUE : defaultValue; + this.isDefault = true; + } else { + if (type == Boolean.class) { + this.value = Boolean.parseBoolean(propertyValue); + } else if (type == String.class) { + this.value = propertyValue; } else { - if (type == Boolean.class) { - this.value = Boolean.parseBoolean(propertyValue); - } else if (type == String.class) { - this.value = propertyValue; - } else { - throw new JVMCIError("Unexpected option type " + type); - } - this.isDefault = false; + throw new JVMCIError("Unexpected option type " + type); } + this.isDefault = false; + } + } + + @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "sentinel must be String since it's a static final in an enum") + private Object getValue() { + if (value == NULL_VALUE) { + return null; + } + if (value == null) { + return defaultValue; } - return value == NULL_VALUE ? null : value; + return value; } /** @@ -342,6 +362,61 @@ public static void printProperties(PrintStream out) { } } } + + /** + * Compute string similarity based on Dice's coefficient. + * + * Ported from str_similar() in globals.cpp. + */ + static float stringSimiliarity(String str1, String str2) { + int hit = 0; + for (int i = 0; i < str1.length() - 1; ++i) { + for (int j = 0; j < str2.length() - 1; ++j) { + if ((str1.charAt(i) == str2.charAt(j)) && (str1.charAt(i + 1) == str2.charAt(j + 1))) { + ++hit; + break; + } + } + } + return 2.0f * hit / (str1.length() + str2.length()); + } + + private static final float FUZZY_MATCH_THRESHOLD = 0.7F; + + /** + * Parses all system properties starting with {@value #JVMCI_OPTION_PROPERTY_PREFIX} and + * initializes the options based on their values. + */ + static void parse() { + Map savedProps = jdk.vm.ci.services.Services.getSavedProperties(); + for (Map.Entry e : savedProps.entrySet()) { + String name = e.getKey(); + if (name.startsWith(Option.JVMCI_OPTION_PROPERTY_PREFIX)) { + Object value = options.get(name); + if (value == null) { + List matches = new ArrayList<>(); + for (String pn : options.keySet()) { + float score = stringSimiliarity(pn, name); + if (score >= FUZZY_MATCH_THRESHOLD) { + matches.add(pn); + } + } + Formatter msg = new Formatter(); + msg.format("Could not find option %s", name); + if (!matches.isEmpty()) { + msg.format("%nDid you mean one of the following?"); + for (String match : matches) { + msg.format("%n %s=", match); + } + } + throw new IllegalArgumentException(msg.toString()); + } else if (value instanceof Option) { + Option option = (Option) value; + option.init(e.getValue()); + } + } + } + } } private static HotSpotJVMCIBackendFactory findFactory(String architecture) { @@ -462,6 +537,9 @@ private HotSpotJVMCIRuntime() { System.setErr(vmLogStream); } + // Initialize the Option values. + Option.parse(); + String hostArchitecture = config.getHostArchitectureName(); HotSpotJVMCIBackendFactory factory; @@ -720,17 +798,25 @@ private HotSpotCompilationRequestResult compileMethod(HotSpotResolvedJavaMethod return hsResult; } + /** + * Guard to ensure shut down actions are performed at most once. + */ + private boolean isShutdown; + /** * Shuts down the runtime. */ @VMEntryPoint - private void shutdown() throws Exception { - // Cleaners are normally only processed when a new Cleaner is - // instantiated so process all remaining cleaners now. - Cleaner.clean(); - - for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) { - vmEventListener.notifyShutdown(); + private synchronized void shutdown() throws Exception { + if (!isShutdown) { + isShutdown = true; + // Cleaners are normally only processed when a new Cleaner is + // instantiated so process all remaining cleaners now. + Cleaner.clean(); + + for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) { + vmEventListener.notifyShutdown(); + } } } @@ -922,8 +1008,8 @@ public int getArrayIndexScale(JavaKind kind) { * * * The implementation of the native {@code JCompile.compile0} method would be in the JVMCI - * shared library that contains the bulk of the JVMCI compiler. The {@code JCompile.compile0} - * implementation will be exported as the following JNI-compatible symbol: + * shared library that contains the JVMCI compiler. The {@code JCompile.compile0} implementation + * must be exported as the following JNI-compatible symbol: * *

      * Java_com_jcompile_JCompile_compile0
@@ -934,9 +1020,18 @@ public int getArrayIndexScale(JavaKind kind) {
      * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/invocation.html#invocation_api_functions"
      *
      *
-     * @return an array of 4 longs where the first value is the {@code JavaVM*} value representing
-     *         the Java VM in the JVMCI shared library, and the remaining values are the first 3
-     *         pointers in the Invocation API function table (i.e., {@code JNIInvokeInterface})
+     * @return info about the Java VM in the JVMCI shared library {@code JavaVM*}. The info is
+     *         encoded in a long array as follows:
+     *
+     *         
+     *     long[] info = {
+     *         javaVM, // the {@code JavaVM*} value
+     *         javaVM->functions->reserved0,
+     *         javaVM->functions->reserved1,
+     *         javaVM->functions->reserved2
+     *     }
+     *         
+ * * @throws NullPointerException if {@code clazz == null} * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e. * {@code -XX:-UseJVMCINativeLibrary}) @@ -1025,6 +1120,8 @@ public long getCurrentJavaThread() { * {@code -XX:-UseJVMCINativeLibrary}) * @throws IllegalStateException if the peer runtime has not been initialized or there is an * error while trying to attach the thread + * @throws ArrayIndexOutOfBoundsException if {@code javaVMInfo} is non-null and is shorter than + * the length of the array returned by {@link #registerNativeMethods} */ public boolean attachCurrentThread(boolean asDaemon) { return compilerToVm.attachCurrentThread(asDaemon); diff --git a/src/jdk.internal.vm.compiler/share/classes/module-info.java b/src/jdk.internal.vm.compiler/share/classes/module-info.java index 4cbd064fb74..a864590fbf2 100644 --- a/src/jdk.internal.vm.compiler/share/classes/module-info.java +++ b/src/jdk.internal.vm.compiler/share/classes/module-info.java @@ -38,7 +38,7 @@ uses org.graalvm.compiler.hotspot.HotSpotBackendFactory; uses org.graalvm.compiler.hotspot.HotSpotCodeCacheListener; uses org.graalvm.compiler.hotspot.HotSpotGraalManagementRegistration; - uses org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory; + uses org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginFactory; uses org.graalvm.compiler.phases.common.jmx.HotSpotMBeanOperationProvider; uses org.graalvm.compiler.serviceprovider.JMXService; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java index bbab79683ab..bdaddf776bb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java @@ -208,7 +208,7 @@ public void ubfm(int size, Register dst, Register src, int r, int s) { } @Override - protected void sbfm(int size, Register dst, Register src, int r, int s) { + public void sbfm(int size, Register dst, Register src, int r, int s) { super.sbfm(size, dst, src, r, s); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java index db9a289e5ee..026eefd9a81 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java @@ -1852,7 +1852,7 @@ public void ubfm(int size, Register dst, Register src, int r, int s) { * @param r must be in the range 0 to size - 1 * @param s must be in the range 0 to size - 1 */ - protected void sbfm(int size, Register dst, Register src, int r, int s) { + public void sbfm(int size, Register dst, Register src, int r, int s) { bitfieldInstruction(SBFM, dst, src, r, s, generalFromSize(size)); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64BitFieldTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64BitFieldTest.java index 7902694a4e0..d123da17cee 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64BitFieldTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64BitFieldTest.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2019, Arm Limited and affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Arm Limited and affiliates. All rights reserved. * 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,12 +36,16 @@ public class AArch64BitFieldTest extends AArch64MatchRuleTest { private static final Predicate predicate = op -> (op instanceof AArch64BitFieldOp); private void testAndCheckLIR(String method, String negativeMethod, Object input) { - test(method, input); - checkLIR(method, predicate, 1); + testAndCheckLIR(method, input); test(negativeMethod, input); checkLIR(negativeMethod, predicate, 0); } + private void testAndCheckLIR(String method, Object input) { + test(method, input); + checkLIR(method, predicate, 1); + } + /** * unsigned bit field extract int. */ @@ -133,4 +137,174 @@ public static long invalidInsertLong(long input) { public void testInsertLong() { testAndCheckLIR("insertLong", "invalidInsertLong", 0xdeadbeefdeadbeefL); } + + // Tests for unsigned bitfield move, with integration of zero extend (I2L) operation. + // + // UBFIZ with I2L. + public static long unsignedInsertExtend(int input) { + return ((long) (input & 0xffff)) << 8; + } + + @Test + public void testUnsignedInsertExtend() { + testAndCheckLIR("unsignedInsertExtend", 0x234); + } + + // I2L with UBFIZ. + public static long unsignedExtendInsert(int input) { + return (input & 0xfff) << 5; + } + + @Test + public void testUnsignedExtendInsert() { + testAndCheckLIR("unsignedExtendInsert", 0x4334); + } + + // I2L with UBFX. + public static long unsignedExtendExtract(int input) { + return (input >>> 6) & 0xffffff; + } + + @Test + public void testUnsignedExtendExtract() { + testAndCheckLIR("unsignedExtendExtract", 0x325ab); + } + + // Signed bitfield insert with extend, generated by (LeftShift (SignExtend value) a) match + // rule. + // SBFIZ with B2L. + public long signedB2LInsert(long input) { + byte b = (byte) input; + return ((long) b) << 2; + } + + @Test + public void testSignedB2LInsert() { + testAndCheckLIR("signedB2LInsert", 0xab3213efL); + } + + // SBFIZ with S2L. + public long signedS2LInsert(long input) { + short s = (short) input; + return ((long) s) << -5; + } + + @Test + public void testSignedS2LInsert() { + testAndCheckLIR("signedS2LInsert", 0x328032bL); + } + + // SBFIZ with I2L. + public static long signedI2LInsert(int input) { + return ((long) input) << 1; + } + + @Test + public void testSignedI2LInsert() { + testAndCheckLIR("signedI2LInsert", 31); + } + + // SBFIZ with B2I. + public int signedB2IInsert(int input) { + byte b = (byte) input; + return b << 31; + } + + @Test + public void testSignedB2IInsert() { + testAndCheckLIR("signedB2IInsert", 0x23); + } + + // SBFIZ with S2I. + public int signedS2IInsert(int input) { + short s = (short) input; + return s << 2; + } + + @Test + public void testSignedS2IInsert() { + testAndCheckLIR("signedS2IInsert", 0x92); + } + + // Tests for bitfield move generated by ([Unsigned]RightShift (LeftShift value a) b) match + // rules. + // SBFX for int. + public static int signedExtractInt(int input) { + return (input << 8) >> 15; + } + + @Test + public void testSignedExtractInt() { + testAndCheckLIR("signedExtractInt", 0x123); + } + + // SBFX for long. + public static long signedExtractLong(long input) { + return (input << 8) >> 15; + } + + @Test + public void testSignedExtractLong() { + testAndCheckLIR("signedExtractLong", 0x125L); + } + + // SBFIZ for int. + public static int signedInsertInt(int input) { + return (input << 15) >> 8; + } + + @Test + public void testSignedInsertInt() { + testAndCheckLIR("signedInsertInt", 0x1253); + } + + // SBFIZ for long. + public static long signedInsertLong(long input) { + return (input << 15) >> 8; + } + + @Test + public void testSignedInsertLong() { + testAndCheckLIR("signedInsertLong", 0xabcddbc325L); + } + + // UBFX for int. + public static int unsignedExtractInt(int input) { + return (input << 8) >>> 31; + } + + @Test + public void testUnsignedExtractInt() { + testAndCheckLIR("unsignedExtractInt", 0x125); + } + + // UBFX for long. + public static long unsignedExtractLong(long input) { + return (input << 8) >>> 12; + } + + @Test + public void testUnsignedExtractLong() { + testAndCheckLIR("unsignedExtractLong", 0x32222e125L); + } + + // UBFIZ for int. + public static int unsignedInsertInt(int input) { + return (input << 15) >>> 8; + } + + @Test + public void testUnsignedInsertInt() { + testAndCheckLIR("unsignedInsertInt", 125); + } + + // UBFIZ for long. + public static long unsignedInsertLong(long input) { + return (input << 63) >>> 1; + } + + @Test + public void testUnsignedInsertLong() { + testAndCheckLIR("unsignedInsertLong", 0x2339fb125L); + } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java index 3af4f1d9c20..c32382af41b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java @@ -371,7 +371,7 @@ private void emitBinaryVar(Variable result, AArch64ArithmeticOp op, AllocatableV } } - private void emitBinaryConst(Variable result, AArch64ArithmeticOp op, AllocatableValue a, JavaConstant b) { + public void emitBinaryConst(Variable result, AArch64ArithmeticOp op, AllocatableValue a, JavaConstant b) { AllocatableValue x = moveSp(a); getLIRGen().append(new AArch64ArithmeticOp.BinaryConstOp(op, result, x, b)); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java index cfc21263a89..31d309b7f9f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java @@ -42,6 +42,7 @@ import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp; import org.graalvm.compiler.lir.aarch64.AArch64BitFieldOp; +import org.graalvm.compiler.lir.aarch64.AArch64BitFieldOp.BitFieldOpCode; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.ConstantNode; @@ -73,6 +74,7 @@ import jdk.vm.ci.aarch64.AArch64Kind; import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.Value; @@ -96,8 +98,8 @@ public class AArch64NodeMatchRules extends NodeMatchRules { binaryOpMap.put(UnsignedRightShiftNode.class, AArch64ArithmeticOp.LSHR); bitFieldOpMap = EconomicMap.create(Equivalence.IDENTITY, 2); - bitFieldOpMap.put(UnsignedRightShiftNode.class, AArch64BitFieldOp.BitFieldOpCode.UBFX); - bitFieldOpMap.put(LeftShiftNode.class, AArch64BitFieldOp.BitFieldOpCode.UBFIZ); + bitFieldOpMap.put(UnsignedRightShiftNode.class, BitFieldOpCode.UBFX); + bitFieldOpMap.put(LeftShiftNode.class, BitFieldOpCode.UBFIZ); logicalNotOpMap = EconomicMap.create(Equivalence.IDENTITY, 3); logicalNotOpMap.put(AndNode.class, AArch64ArithmeticOp.BIC); @@ -161,19 +163,6 @@ private AllocatableValue moveSp(AllocatableValue value) { return getLIRGeneratorTool().moveSp(value); } - private ComplexMatchResult emitBitField(AArch64BitFieldOp.BitFieldOpCode op, ValueNode value, int lsb, int width) { - assert op != null; - assert value.getStackKind().isNumericInteger(); - - return builder -> { - Value a = operand(value); - Variable result = gen.newVariable(LIRKind.combine(a)); - AllocatableValue src = moveSp(gen.asAllocatable(a)); - gen.append(new AArch64BitFieldOp(op, result, src, lsb, width)); - return result; - }; - } - private ComplexMatchResult emitBinaryShift(AArch64ArithmeticOp op, ValueNode value, BinaryNode shift) { AArch64MacroAssembler.ShiftType shiftType = shiftTypeMap.get(shift.getClass()); assert shiftType != null; @@ -205,6 +194,51 @@ private ComplexMatchResult emitBitTestAndBranch(FixedNode trueSuccessor, FixedNo }; } + private ComplexMatchResult emitBitField(JavaKind kind, AArch64BitFieldOp.BitFieldOpCode op, ValueNode value, int lsb, int width) { + assert op != null; + assert value.getStackKind().isNumericInteger(); + + return builder -> { + Value a = operand(value); + LIRKind resultKind = LIRKind.fromJavaKind(gen.target().arch, kind); + Variable result = gen.newVariable(resultKind); + AllocatableValue src = moveSp(gen.asAllocatable(a)); + gen.append(new AArch64BitFieldOp(op, result, src, lsb, width)); + return result; + }; + } + + private ComplexMatchResult emitUnsignedBitField(JavaKind kind, BinaryNode shift, ValueNode value, ConstantNode scale, ConstantNode mask) { + assert kind.isNumericInteger(); + BitFieldOpCode op = bitFieldOpMap.get(shift.getClass()); + assert op != null; + JavaKind srcKind = shift.getStackKind(); + // The Java(R) Language Specification CHAPTER 15.19 Shift Operators says: + // "If the promoted type of the left-hand operand is int(long), then only the five(six) + // lowest-order bits of the right-hand operand are used as the shift distance." + int distance = scale.asJavaConstant().asInt(); + int lsb = distance & (srcKind == JavaKind.Int ? 0x1F : 0x3F); + + long maskValue = mask.asJavaConstant().asLong(); + // Constraint 1: Mask plus one should be a power-of-2 integer. + if (!CodeUtil.isPowerOf2(maskValue + 1)) { + return null; + } + int width = CodeUtil.log2(maskValue + 1); + int srcBits = srcKind.getBitCount(); + // Constraint 2: Bit field width is less than 31(63) for int(long) as any bit field move + // operations can be done by a single shift instruction if the width is 31(63). + if (width >= srcBits - 1) { + return null; + } + // Constraint 3: Sum of bit field width and the shift distance is less or equal to 32(64) + // for int(long) as the specification of AArch64 bit field instructions. + if (width + distance > srcBits) { + return null; + } + return emitBitField(kind, op, value, lsb, width); + } + private static boolean isNarrowingLongToInt(NarrowNode narrow) { return narrow.getInputBits() == Long.SIZE && narrow.getResultBits() == Integer.SIZE; } @@ -325,38 +359,68 @@ public ComplexMatchResult extendedPointerAddShift(AArch64PointerAddNode addP) { return null; } - @MatchRule("(And (UnsignedRightShift=shift a Constant=b) Constant=c)") - @MatchRule("(LeftShift=shift (And a Constant=c) Constant=b)") - public ComplexMatchResult unsignedBitField(BinaryNode shift, ValueNode a, ConstantNode b, ConstantNode c) { - JavaKind srcKind = a.getStackKind(); - assert srcKind.isNumericInteger(); - AArch64BitFieldOp.BitFieldOpCode op = bitFieldOpMap.get(shift.getClass()); - assert op != null; - int distance = b.asJavaConstant().asInt(); - long mask = c.asJavaConstant().asLong(); + @MatchRule("(And (UnsignedRightShift=shift value Constant=a) Constant=b)") + @MatchRule("(LeftShift=shift (And value Constant=b) Constant=a)") + public ComplexMatchResult unsignedBitField(BinaryNode shift, ValueNode value, ConstantNode a, ConstantNode b) { + JavaKind kind = shift.getStackKind(); + return emitUnsignedBitField(kind, shift, value, a, b); + } - // The Java(R) Language Specification CHAPTER 15.19 Shift Operators says: - // "If the promoted type of the left-hand operand is int(long), then only the five(six) - // lowest-order bits of the right-hand operand are used as the shift distance." - distance = distance & (srcKind == JavaKind.Int ? 0x1f : 0x3f); + @MatchRule("(LeftShift=shift (ZeroExtend=extend (And value Constant=b)) Constant=a)") + @MatchRule("(ZeroExtend=extend (And (UnsignedRightShift=shift value Constant=a) Constant=b))") + @MatchRule("(ZeroExtend=extend (LeftShift=shift (And value Constant=b) Constant=a))") + public ComplexMatchResult unsignedExtBitField(ZeroExtendNode extend, BinaryNode shift, ValueNode value, ConstantNode a, ConstantNode b) { + JavaKind kind = extend.getStackKind(); + return emitUnsignedBitField(kind, shift, value, a, b); + } - // Constraint 1: Mask plus one should be a power-of-2 integer. - if (!CodeUtil.isPowerOf2(mask + 1)) { - return null; - } - int width = CodeUtil.log2(mask + 1); + @MatchRule("(LeftShift=shift (SignExtend value) Constant)") + public ComplexMatchResult signedBitField(LeftShiftNode shift) { + JavaKind kind = shift.getStackKind(); + assert kind.isNumericInteger(); + + SignExtendNode extend = (SignExtendNode) shift.getX(); + int srcBits = extend.getInputBits(); + int resultBits = extend.getResultBits(); + assert kind.getBitCount() == resultBits; + + int lsb = shift.getY().asJavaConstant().asInt() & (resultBits - 1); + // Get the min value of the srcBits and (resultBits - lsb) as the bitfield width. + int width = Math.min(srcBits, resultBits - lsb); + assert width >= 1 && width <= resultBits - lsb; + + ValueNode value = extend.getValue(); + return emitBitField(kind, BitFieldOpCode.SBFIZ, value, lsb, width); + } + + @MatchRule("(RightShift=rshift (LeftShift=lshift value Constant) Constant)") + @MatchRule("(UnsignedRightShift=rshift (LeftShift=lshift value Constant) Constant)") + public ComplexMatchResult bitFieldMove(BinaryNode rshift, LeftShiftNode lshift) { + JavaKind srcKind = rshift.getStackKind(); + assert srcKind.isNumericInteger(); int srcBits = srcKind.getBitCount(); - // Constraint 2: Bit field width is less than 31(63) for int(long) as any bit field move - // operations can be done by a single shift instruction if the width is 31(63). - if (width >= srcBits - 1) { + int lshiftNum = lshift.getY().asJavaConstant().asInt() & (srcBits - 1); + int rshiftNum = rshift.getY().asJavaConstant().asInt() & (srcBits - 1); + int lsb = Math.abs(lshiftNum - rshiftNum); + assert lsb >= 0 && lsb <= (srcBits - 1); + + // Get the width of the bitField. It should be in the range 1 to 32(64)-. + int width = srcBits - Math.max(lshiftNum, rshiftNum); + if (width > (srcBits - lsb) || width < 1) { return null; } - // Constraint 3: Sum of bit field width and the shift distance is less or equal to 32(64) - // for int(long) as the specification of AArch64 bit field instructions. - if (width + distance > srcBits) { - return null; + + // Use bitfield insert (SBFIZ/UBFIZ) if left shift number is larger than right shift number, + // otherwise use bitfield extract (SBFX/UBFX). + boolean bitFieldInsert = lshiftNum > rshiftNum; + BitFieldOpCode op; + if (rshift instanceof RightShiftNode) { + op = bitFieldInsert ? BitFieldOpCode.SBFIZ : BitFieldOpCode.SBFX; + } else { + assert rshift instanceof UnsignedRightShiftNode; + op = bitFieldInsert ? BitFieldOpCode.UBFIZ : BitFieldOpCode.UBFX; } - return emitBitField(op, a, distance, width); + return emitBitField(srcKind, op, lshift.getX(), lsb, width); } @MatchRule("(Or=op (LeftShift=x src Constant=shiftAmt1) (UnsignedRightShift src Constant=shiftAmt2))") @@ -375,9 +439,11 @@ public ComplexMatchResult rotationConstant(ValueNode op, ValueNode x, ValueNode } if ((0 == shift1 + shift2) || (src.getStackKind().getBitCount() == shift1 + shift2)) { return builder -> { - Value a = operand(src); - Value b = x instanceof LeftShiftNode ? operand(shiftAmt2) : operand(shiftAmt1); - return getArithmeticLIRGenerator().emitBinary(LIRKind.combine(a, b), AArch64ArithmeticOp.ROR, false, a, b); + AllocatableValue a = gen.asAllocatable(operand(src)); + JavaConstant b = x instanceof LeftShiftNode ? shiftAmt2.asJavaConstant() : shiftAmt1.asJavaConstant(); + Variable result = gen.newVariable(LIRKind.combine(a)); + getArithmeticLIRGenerator().emitBinaryConst(result, AArch64ArithmeticOp.ROR, a, b); + return result; }; } return null; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java index 9d70e2d2771..d45e47aeb60 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java @@ -692,21 +692,26 @@ public Variable emitXor(Value a, Value b) { } private Variable emitShift(AMD64Shift op, OperandSize size, Value a, Value b) { + if (isJavaConstant(b)) { + return emitShiftConst(op, size, a, asJavaConstant(b)); + } Variable result = getLIRGen().newVariable(LIRKind.combine(a, b).changeType(a.getPlatformKind())); AllocatableValue input = asAllocatable(a); - if (isJavaConstant(b)) { - JavaConstant c = asJavaConstant(b); - if (c.asLong() == 1) { - getLIRGen().append(new AMD64Unary.MOp(op.m1Op, size, result, input)); - } else { - /* - * c needs to be masked here, because shifts with immediate expect a byte. - */ - getLIRGen().append(new AMD64Binary.ConstOp(op.miOp, size, result, input, (byte) c.asLong())); - } + getLIRGen().emitMove(RCX_I, b); + getLIRGen().append(new AMD64ShiftOp(op.mcOp, size, result, input, RCX_I)); + return result; + } + + public Variable emitShiftConst(AMD64Shift op, OperandSize size, Value a, JavaConstant b) { + Variable result = getLIRGen().newVariable(LIRKind.combine(a).changeType(a.getPlatformKind())); + AllocatableValue input = asAllocatable(a); + if (b.asLong() == 1) { + getLIRGen().append(new AMD64Unary.MOp(op.m1Op, size, result, input)); } else { - getLIRGen().emitMove(RCX_I, b); - getLIRGen().append(new AMD64ShiftOp(op.mcOp, size, result, input, RCX_I)); + /* + * c needs to be masked here, because shifts with immediate expect a byte. + */ + getLIRGen().append(new AMD64Binary.ConstOp(op.miOp, size, result, input, (byte) b.asLong())); } return result; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java index 08f228cabaf..699f26254fc 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java @@ -33,6 +33,7 @@ import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSX; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSXB; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp.MOVSXD; +import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64Shift.ROL; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VADDSD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VADDSS; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VMULSD; @@ -449,8 +450,15 @@ public ComplexMatchResult ifLogicCas(IfNode root, CompareNode compare, ValueNode @MatchRule("(Or (LeftShift=lshift value Constant) (UnsignedRightShift=rshift value Constant))") public ComplexMatchResult rotateLeftConstant(LeftShiftNode lshift, UnsignedRightShiftNode rshift) { - if ((lshift.getShiftAmountMask() & (lshift.getY().asJavaConstant().asInt() + rshift.getY().asJavaConstant().asInt())) == 0) { - return builder -> getArithmeticLIRGenerator().emitRol(operand(lshift.getX()), operand(lshift.getY())); + JavaConstant lshiftConst = lshift.getY().asJavaConstant(); + JavaConstant rshiftConst = rshift.getY().asJavaConstant(); + if ((lshift.getShiftAmountMask() & (lshiftConst.asInt() + rshiftConst.asInt())) == 0) { + return builder -> { + Value a = operand(lshift.getX()); + OperandSize size = OperandSize.get(a.getPlatformKind()); + assert size == OperandSize.DWORD || size == OperandSize.QWORD; + return getArithmeticLIRGenerator().emitShiftConst(ROL, size, a, lshiftConst); + }; } return null; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java index b77cb641919..428dc179738 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java @@ -343,11 +343,16 @@ static class TypeDescriptor { final boolean commutative; /** - * Can multiple users of this node subsume it. Constants can be swallowed into a match even - * if there are multiple users. + * Can multiple users of this node subsume it. */ final boolean shareable; + /** + * Can this node be swallowed into a match. Constants can be consumed by a match even if it + * has multiple users. + */ + final boolean consumable; + /** * Can this node be subsumed into a match even if there are side effecting nodes between * this node and the match. @@ -356,7 +361,8 @@ static class TypeDescriptor { final Set originatingElements = new HashSet<>(); - TypeDescriptor(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List inputs, boolean commutative, boolean shareable, boolean ignoresSideEffects) { + TypeDescriptor(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List inputs, + boolean commutative, boolean shareable, boolean consumable, boolean ignoresSideEffects) { this.mirror = mirror; this.shortName = shortName; this.nodeClass = nodeClass; @@ -364,6 +370,7 @@ static class TypeDescriptor { this.inputs = inputs; this.commutative = commutative; this.shareable = shareable; + this.consumable = consumable; this.ignoresSideEffects = ignoresSideEffects; assert !commutative || inputs.size() == 2; } @@ -376,9 +383,9 @@ static class TypeDescriptor { private TypeDescriptor valueType; - private void declareType(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List inputs, boolean commutative, boolean shareable, boolean ignoresSideEffects, - Element element) { - TypeDescriptor descriptor = new TypeDescriptor(mirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, ignoresSideEffects); + private void declareType(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List inputs, + boolean commutative, boolean shareable, boolean consumable, boolean ignoresSideEffects, Element element) { + TypeDescriptor descriptor = new TypeDescriptor(mirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, consumable, ignoresSideEffects); descriptor.originatingElements.add(element); knownTypes.put(shortName, descriptor); } @@ -461,7 +468,7 @@ List generateVariants() { private String formatPrefix() { if (nodeType == valueType) { - return String.format("new MatchPattern(%s, false, false", name != null ? ("\"" + name + "\"") : "null"); + return String.format("new MatchPattern(%s, false, false, false", name != null ? ("\"" + name + "\"") : "null"); } else { return String.format("new MatchPattern(%s.class, %s", nodeType.nodeClass, name != null ? ("\"" + name + "\"") : "null"); } @@ -470,13 +477,13 @@ private String formatPrefix() { private String formatSuffix() { if (nodeType != null) { if (inputs.length != nodeType.inputs.size()) { - return ", true, " + nodeType.ignoresSideEffects + ")"; + return ", true, " + nodeType.consumable + ", " + nodeType.ignoresSideEffects + ")"; } else { if (nodeType.inputs.size() > 0) { - return ", " + nodeType.nodeClass + "_positions, " + !nodeType.shareable + ", " + nodeType.ignoresSideEffects + ")"; + return ", " + nodeType.nodeClass + "_positions, " + !nodeType.shareable + ", " + nodeType.consumable + ", " + nodeType.ignoresSideEffects + ")"; } if (nodeType.shareable) { - return ", false, " + nodeType.ignoresSideEffects + ")"; + return ", false, " + nodeType.consumable + ", " + nodeType.ignoresSideEffects + ")"; } } } @@ -732,7 +739,7 @@ public boolean doProcess(Set annotations, RoundEnvironmen // Define a TypeDescriptor for the generic node but don't enter it into the nodeTypes // table since it shouldn't be mentioned in match rules. TypeMirror valueTypeMirror = getTypeElement(VALUE_NODE_CLASS_NAME).asType(); - valueType = new TypeDescriptor(valueTypeMirror, "Value", "ValueNode", "org.graalvm.compiler.nodes", Collections.emptyList(), false, false, false); + valueType = new TypeDescriptor(valueTypeMirror, "Value", "ValueNode", "org.graalvm.compiler.nodes", Collections.emptyList(), false, false, false, false); Map map = new HashMap<>(); @@ -842,8 +849,9 @@ private void processMatchableNode(Element element, TypeElement topDeclaringType, boolean commutative = getAnnotationValue(matchable, "commutative", Boolean.class); boolean shareable = getAnnotationValue(matchable, "shareable", Boolean.class); + boolean consumable = getAnnotationValue(matchable, "consumable", Boolean.class); boolean ignoresSideEffects = getAnnotationValue(matchable, "ignoresSideEffects", Boolean.class); - declareType(nodeClassMirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, ignoresSideEffects, element); + declareType(nodeClassMirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, consumable, ignoresSideEffects, element); } private void processMatchRules(Map map, Element element, List matchRules) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java index 92f037939ae..06d25f51117 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java @@ -538,7 +538,7 @@ private static void checkOptionFieldUsages(List errors, Map reference * ACCEPTABLE_FACTOR) { + fail("Compilation of the loop nest is too slow. loops: %dms > %d * reference: %dms", loops, ACCEPTABLE_FACTOR, reference); + } } public long time(String methodName) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnschedulableGraphTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnschedulableGraphTest.java index 7d858de3aab..2baffb29e8f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnschedulableGraphTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnschedulableGraphTest.java @@ -105,7 +105,7 @@ public void test01() { try (AutoCloseable c = new TTY.Filter(); DebugContext debug = getDebugContext(method); DebugCloseable s = debug.disableIntercept()) { - test("snippet01", 0, 1, 2); + test(debug.getOptions(), "snippet01", 0, 1, 2); Assert.fail("Compilation should not reach this point, must throw an exception before"); } catch (Throwable t) { if (t.getMessage().contains("liveIn set of first block must be empty")) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java index ba49fff899a..d95d5696b6d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java @@ -188,17 +188,28 @@ private static void checkForRequestedCrash(StructuredGraph graph) { } } if (crashLabel != null) { + String crashMessage = "Forced crash after compiling " + crashLabel; + notifyCrash(crashMessage); if (permanentBailout) { - throw new PermanentBailoutException("Forced crash after compiling " + crashLabel); + throw new PermanentBailoutException(crashMessage); } if (bailout) { - throw new RetryableBailoutException("Forced crash after compiling " + crashLabel); + throw new RetryableBailoutException(crashMessage); } - throw new RuntimeException("Forced crash after compiling " + crashLabel); + throw new RuntimeException(crashMessage); } } } + /** + * Substituted by {@code com.oracle.svm.graal.hotspot.libgraal. + * Target_org_graalvm_compiler_core_GraalCompiler} to optionally test routing fatal error + * handling from libgraal to HotSpot. + */ + @SuppressWarnings("unused") + private static void notifyCrash(String crashMessage) { + } + /** * Builds the graph, optimizes it. */ diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java index 07725a45a56..723c28f041c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java @@ -30,6 +30,7 @@ import static org.graalvm.compiler.core.common.GraalOptions.MatchExpressions; import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.AllTargets; import static org.graalvm.compiler.core.common.SpeculativeExecutionAttacksMitigations.Options.MitigateSpeculativeExecutionAttacks; +import static org.graalvm.compiler.core.match.ComplexMatchValue.INTERIOR_MATCH; import static org.graalvm.compiler.debug.DebugOptions.LogVerbose; import static org.graalvm.compiler.lir.LIR.verifyBlock; @@ -137,6 +138,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio private final NodeMatchRules nodeMatchRules; private EconomicMap, List> matchRules; + private EconomicMap sharedMatchCounts; public NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, NodeMatchRules nodeMatchRules) { this.gen = (LIRGenerator) gen; @@ -146,6 +148,7 @@ public NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, NodeMatchRule OptionValues options = graph.getOptions(); if (MatchExpressions.getValue(options)) { matchRules = MatchRuleRegistry.lookup(nodeMatchRules.getClass(), options, graph.getDebug()); + sharedMatchCounts = EconomicMap.create(); } traceLIRGeneratorLevel = TTY.isSuppressed() ? 0 : Options.TraceLIRGeneratorLevel.getValue(options); @@ -219,13 +222,30 @@ public Value setResult(ValueNode x, Value operand) { * ValueNodes. */ public void setMatchResult(Node x, Value operand) { - assert operand.equals(ComplexMatchValue.INTERIOR_MATCH) || operand instanceof ComplexMatchValue; + assert operand.equals(INTERIOR_MATCH) || operand instanceof ComplexMatchValue; assert operand instanceof ComplexMatchValue || MatchPattern.isSingleValueUser(x) : "interior matches must be single user"; assert nodeOperands != null && nodeOperands.get(x) == null : "operand cannot be set twice"; assert !(x instanceof VirtualObjectNode); nodeOperands.set(x, operand); } + /** + * Track how many users have consumed a sharedable match and disable emission of the value if + * all users have consumed it. + */ + public void incrementSharedMatchCount(Node node) { + assert nodeOperands != null && nodeOperands.get(node) == null : "operand cannot be set twice"; + Integer matchValue = sharedMatchCounts.get(node); + if (matchValue == null) { + matchValue = 0; + } + matchValue = matchValue + 1; + sharedMatchCounts.put(node, matchValue); + if (node.getUsageCount() == matchValue) { + nodeOperands.set(node, INTERIOR_MATCH); + } + } + public LabelRef getLIRBlock(FixedNode b) { assert gen.getResult().getLIR().getControlFlowGraph() instanceof ControlFlowGraph; Block result = ((ControlFlowGraph) gen.getResult().getLIR().getControlFlowGraph()).blockFor(b); @@ -384,7 +404,7 @@ public void doBlock(Block block, StructuredGraph graph, BlockMap> blo throw new GraalGraphError(e).addContext(valueNode); } } - } else if (ComplexMatchValue.INTERIOR_MATCH.equals(operand)) { + } else if (INTERIOR_MATCH.equals(operand)) { // Doesn't need to be evaluated debug.log("interior match for %s", valueNode); } else if (operand instanceof ComplexMatchValue) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java index e6e40114576..e297d93b788 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,10 +68,12 @@ public class MatchContext { static final class ConsumedNode { final Node node; final boolean ignoresSideEffects; + final boolean singleUser; - ConsumedNode(Node node, boolean ignoresSideEffects) { + ConsumedNode(Node node, boolean ignoresSideEffects, boolean singleUser) { this.node = node; this.ignoresSideEffects = ignoresSideEffects; + this.singleUser = singleUser; } } @@ -85,11 +87,11 @@ static final class ConsumedNodes implements Iterable { this.nodes = null; } - public void add(Node node, boolean ignoresSideEffects) { + public void add(Node node, boolean ignoresSideEffects, boolean singlerUser) { if (nodes == null) { nodes = new ArrayList<>(2); } - nodes.add(new ConsumedNode(node, ignoresSideEffects)); + nodes.add(new ConsumedNode(node, ignoresSideEffects, singlerUser)); } public boolean contains(Node node) { @@ -373,10 +375,7 @@ public void setResult(ComplexMatchResult result) { if (cn.node == root || cn.node == emitNode) { continue; } - // All the interior nodes should be skipped during the normal doRoot calls in - // NodeLIRBuilder so mark them as interior matches. The root of the match will get a - // closure which will be evaluated to produce the final LIR. - builder.setMatchResult(cn.node, ComplexMatchValue.INTERIOR_MATCH); + setResult(cn); } builder.setMatchResult(emitNode, value); if (root != emitNode) { @@ -387,23 +386,34 @@ public void setResult(ComplexMatchResult result) { } } + private void setResult(ConsumedNode consumedNode) { + Node node = consumedNode.node; + if (consumedNode.singleUser) { + // All the interior nodes should be skipped during the normal doRoot calls in + // NodeLIRBuilder so mark them as interior matches. The root of the match will get a + // closure which will be evaluated to produce the final LIR. + builder.setMatchResult(node, ComplexMatchValue.INTERIOR_MATCH); + return; + } + builder.incrementSharedMatchCount(node); + } + /** * Mark a node as consumed by the match. Consumed nodes will never be evaluated. * * @return Result.OK if the node can be safely consumed. */ - public Result consume(Node node, boolean ignoresSideEffects, boolean atRoot) { + public Result consume(Node node, boolean ignoresSideEffects, boolean atRoot, boolean singleUser) { if (atRoot) { - consumed.add(node, ignoresSideEffects); + consumed.add(node, ignoresSideEffects, singleUser); return Result.OK; } - assert MatchPattern.isSingleValueUser(node) : "should have already been checked"; if (builder.hasOperand(node)) { return Result.alreadyUsed(node, rule.getPattern()); } - consumed.add(node, ignoresSideEffects); + consumed.add(node, ignoresSideEffects, singleUser); return Result.OK; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java index 7e45d859867..bca3ce2ed90 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -158,6 +158,8 @@ public String toString() { */ private final boolean singleUser; + private final boolean consumable; + /** * Can this node be subsumed into a match even if there are side effecting nodes between this * node and the match. @@ -166,41 +168,47 @@ public String toString() { private static final MatchPattern[] EMPTY_PATTERNS = new MatchPattern[0]; - public MatchPattern(String name, boolean singleUser, boolean ignoresSideEffects) { - this(null, name, singleUser, ignoresSideEffects); + public MatchPattern(String name, boolean singleUser, boolean consumable, boolean ignoresSideEffects) { + this(null, name, singleUser, consumable, ignoresSideEffects); } - public MatchPattern(Class nodeClass, String name, boolean singleUser, boolean ignoresSideEffects) { + public MatchPattern(Class nodeClass, String name, boolean singleUser, boolean consumable, boolean ignoresSideEffects) { this.nodeClass = nodeClass; this.name = name; this.singleUser = singleUser; + this.consumable = consumable; this.ignoresSideEffects = ignoresSideEffects; this.patterns = EMPTY_PATTERNS; this.inputs = null; assert !ignoresSideEffects || FloatingNode.class.isAssignableFrom(nodeClass); } - private MatchPattern(Class nodeClass, String name, boolean singleUser, boolean ignoresSideEffects, MatchPattern[] patterns, Position[] inputs) { + private MatchPattern(Class nodeClass, String name, boolean singleUser, boolean consumable, + boolean ignoresSideEffects, MatchPattern[] patterns, Position[] inputs) { assert inputs == null || inputs.length == patterns.length; this.nodeClass = nodeClass; this.name = name; this.singleUser = singleUser; + this.consumable = consumable; this.ignoresSideEffects = ignoresSideEffects; this.patterns = patterns; this.inputs = inputs; assert !ignoresSideEffects || FloatingNode.class.isAssignableFrom(nodeClass); } - public MatchPattern(Class nodeClass, String name, MatchPattern first, Position[] inputs, boolean singleUser, boolean ignoresSideEffects) { - this(nodeClass, name, singleUser, ignoresSideEffects, new MatchPattern[]{first}, inputs); + public MatchPattern(Class nodeClass, String name, MatchPattern first, Position[] inputs, + boolean singleUser, boolean consumable, boolean ignoresSideEffects) { + this(nodeClass, name, singleUser, consumable, ignoresSideEffects, new MatchPattern[]{first}, inputs); } - public MatchPattern(Class nodeClass, String name, MatchPattern first, MatchPattern second, Position[] inputs, boolean singleUser, boolean ignoresSideEffects) { - this(nodeClass, name, singleUser, ignoresSideEffects, new MatchPattern[]{first, second}, inputs); + public MatchPattern(Class nodeClass, String name, MatchPattern first, MatchPattern second, + Position[] inputs, boolean singleUser, boolean consumable, boolean ignoresSideEffects) { + this(nodeClass, name, singleUser, consumable, ignoresSideEffects, new MatchPattern[]{first, second}, inputs); } - public MatchPattern(Class nodeClass, String name, MatchPattern first, MatchPattern second, MatchPattern third, Position[] inputs, boolean singleUser, boolean ignoresSideEffects) { - this(nodeClass, name, singleUser, ignoresSideEffects, new MatchPattern[]{first, second, third}, inputs); + public MatchPattern(Class nodeClass, String name, MatchPattern first, MatchPattern second, MatchPattern third, + Position[] inputs, boolean singleUser, boolean consumable, boolean ignoresSideEffects) { + this(nodeClass, name, singleUser, consumable, ignoresSideEffects, new MatchPattern[]{first, second, third}, inputs); } Class nodeClass() { @@ -234,8 +242,9 @@ private Result matchUsage(Node node, MatchContext context, boolean atRoot) { if (result != Result.OK) { return result; } - if (singleUser) { - result = context.consume(node, ignoresSideEffects, atRoot); + + if (consumable) { + result = context.consume(node, ignoresSideEffects, atRoot, singleUser); if (result != Result.OK) { return result; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchableNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchableNode.java index 38285daa7c8..5ac33f320e3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchableNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchableNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,4 +66,9 @@ boolean shareable() default false; boolean ignoresSideEffects() default false; + + /** + * Can a node be consumed by a matched rule regardless of whether it is shareable. + */ + boolean consumable() default true; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalError.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalError.java index f7922ddc638..11cf94e05cd 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalError.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, 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 @@ -55,6 +55,10 @@ public static RuntimeException shouldNotReachHere(Throwable cause) { throw new GraalError(cause); } + public static RuntimeException shouldNotReachHere(Throwable cause, String msg) { + throw new GraalError(cause, "should not reach here: %s", msg); + } + /** * Checks a given condition and throws a {@link GraalError} if it is false. Guarantees are * stronger than assertions in that they are always checked. Error messages for guarantee diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/IgvDumpChannel.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/IgvDumpChannel.java index c359d9fcb69..0c069a5b05b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/IgvDumpChannel.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/IgvDumpChannel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,7 +81,7 @@ void realClose() throws IOException { WritableByteChannel channel() throws IOException { if (closed) { - throw new IOException(); + throw new IOException("already closed"); } if (sharedChannel == null) { PrintGraphTarget target = DebugOptions.PrintGraph.getValue(options); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java index af6ec435d58..e632ed2010a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java @@ -154,14 +154,18 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { /** * Annotates a method that can be replaced by a compiler intrinsic. A (resolved) call to the * annotated method will be processed by a generated {@code InvocationPlugin} that calls either - * a factory method or a constructor corresponding with the annotated method. + * a factory method or a constructor corresponding with the annotated method. By default the + * intrinsics are implemented by invoking the constructor but a factory method may be used + * instead. To use a factory method the class implementing the intrinsic must be annotated with + * {@link NodeIntrinsicFactory}. To ease error checking of NodeIntrinsics all intrinsics are + * expected to be implemented in the same way, so it's not possible to mix constructor and + * factory intrinsification in the same class. *

* A factory method corresponding to an annotated method is a static method named * {@code intrinsify} defined in the class denoted by {@link #value()}. In order, its signature * is as follows: *

    *
  1. A {@code GraphBuilderContext} parameter.
  2. - *
  3. A {@code ResolvedJavaMethod} parameter.
  4. *
  5. A sequence of zero or more {@linkplain InjectedNodeParameter injected} parameters.
  6. *
  7. Remaining parameters that match the declared parameters of the annotated method.
  8. *
@@ -199,6 +203,15 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { boolean hasSideEffect() default false; } + /** + * Marker annotation indicating that the class uses factory methods instead of constructors for + * intrinsification. + */ + @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) + @java.lang.annotation.Target(ElementType.TYPE) + public @interface NodeIntrinsicFactory { + } + /** * Marker for a node that can be replaced by another node via global value numbering. A * {@linkplain NodeClass#isLeafNode() leaf} node can be replaced by another node of the same diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java index 6251977d764..3d7eff3891a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java @@ -30,10 +30,8 @@ import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled; import static org.graalvm.compiler.graph.InputEdges.translateInto; import static org.graalvm.compiler.graph.Node.WithAllEdges; -import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe; import java.lang.annotation.Annotation; -import java.lang.invoke.MethodHandles; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -54,7 +52,6 @@ import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.graph.Edges.Type; import org.graalvm.compiler.graph.Graph.DuplicationReplacement; @@ -71,6 +68,7 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodeinfo.Verbosity; +import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess; import sun.misc.Unsafe; @@ -84,7 +82,7 @@ */ public final class NodeClass extends FieldIntrospection { - private static final Unsafe UNSAFE = getUnsafe(); + private static final Unsafe UNSAFE = GraalUnsafeAccess.getUnsafe(); // Timers for creation of a NodeClass instance private static final TimerKey Init_FieldScanning = DebugContext.timer("NodeClass.Init.FieldScanning"); private static final TimerKey Init_FieldScanningInner = DebugContext.timer("NodeClass.Init.FieldScanning.Inner"); @@ -132,39 +130,11 @@ private static NodeClass getUnchecked(Class clazz) { } public static NodeClass get(Class clazz) { - int numTries = 0; - while (true) { - @SuppressWarnings("removal") - boolean shouldBeInitializedBefore = UNSAFE.shouldBeInitialized(clazz); - - NodeClass result = getUnchecked(clazz); - if (result != null || clazz == NODE_CLASS) { - return result; - } - - /* - * GR-9537: We observed a transient problem with TYPE fields being null. Retry a couple - * of times and print something to the log so that we can gather more diagnostic - * information without failing gates. - */ - numTries++; - @SuppressWarnings("removal") - boolean shouldBeInitializedAfter = UNSAFE.shouldBeInitialized(clazz); - String msg = "GR-9537 Reflective field access of TYPE field returned null. This is probably a bug in HotSpot class initialization. " + - " clazz: " + clazz.getTypeName() + ", numTries: " + numTries + - ", shouldBeInitializedBefore: " + shouldBeInitializedBefore + ", shouldBeInitializedAfter: " + shouldBeInitializedAfter; - if (numTries <= 100) { - TTY.println(msg); - try { - MethodHandles.lookup().ensureInitialized(clazz); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } else { - throw GraalError.shouldNotReachHere(msg); - } - return result; + NodeClass result = getUnchecked(clazz); + if (result == null && clazz != NODE_CLASS) { + throw GraalError.shouldNotReachHere("TYPE field not initialized for class " + clazz.getTypeName()); } + return result; } private static final Class NODE_CLASS = Node.class; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java index fe1d3a69880..bbc57525a19 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java @@ -395,6 +395,11 @@ private void emitCodeSuffix(CompilationResultBuilder crb, AArch64MacroAssembler ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK); masm.adr(lr, 0); // Warning: the argument is an offset from the instruction! AArch64Call.directJmp(crb, masm, linkage); + if (config.supportsMethodHandleDeoptimizationEntry() && crb.needsMHDeoptHandler()) { + crb.recordMark(HotSpotMarkId.DEOPT_MH_HANDLER_ENTRY); + masm.adr(lr, 0); + AArch64Call.directJmp(crb, masm, linkage); + } } else { // No need to emit the stubs for entries back into the method since // it has no calls that can cause such "return" entries diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java index 4b4fb072421..e563cb2c552 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java @@ -66,7 +66,6 @@ import org.graalvm.compiler.phases.common.AddressLoweringByUsePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; -import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.aarch64.AArch64GraphBuilderPlugins; import org.graalvm.compiler.serviceprovider.ServiceProvider; import org.graalvm.compiler.word.WordTypes; @@ -151,7 +150,7 @@ public HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRuntime, Co lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, platformConfigurationProvider, metaAccessExtensionProvider, target); } - Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, platformConfigurationProvider, + HotSpotProviders p = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider); try (InitTimer rt = timer("create SnippetReflection provider")) { @@ -172,7 +171,7 @@ public HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRuntime, Co suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, replacements); } providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, - snippetReflection, wordTypes, plugins, platformConfigurationProvider, metaAccessExtensionProvider); + snippetReflection, wordTypes, plugins, platformConfigurationProvider, metaAccessExtensionProvider, config); replacements.setProviders(providers); replacements.maybeInitializeEncoder(options); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectStaticCallOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectStaticCallOp.java index 845d0ee7898..0f4cab6c586 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectStaticCallOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectStaticCallOp.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.Value; @@ -69,6 +70,9 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { // correct inline cache value here. crb.recordMark(invokeKind == InvokeKind.Static ? HotSpotMarkId.INVOKESTATIC : HotSpotMarkId.INVOKESPECIAL); masm.movNativeAddress(inlineCacheRegister, config.nonOopBits); + if (config.supportsMethodHandleDeoptimizationEntry() && config.isMethodHandleCall((HotSpotResolvedJavaMethod) callTarget) && invokeKind != InvokeKind.Static) { + crb.setNeedsMHDeoptHandler(); + } super.emitCode(crb, masm); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectVirtualCallOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectVirtualCallOp.java index 9a5decc1567..9dd4880f5fe 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectVirtualCallOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotDirectVirtualCallOp.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.Value; @@ -69,6 +70,9 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { // correct inline cache value here. crb.recordMark(invokeKind == InvokeKind.Virtual ? HotSpotMarkId.INVOKEVIRTUAL : HotSpotMarkId.INVOKEINTERFACE); masm.movNativeAddress(inlineCacheRegister, config.nonOopBits); + if (config.supportsMethodHandleDeoptimizationEntry() && config.isMethodHandleCall((HotSpotResolvedJavaMethod) callTarget)) { + crb.setNeedsMHDeoptHandler(); + } super.emitCode(crb, masm); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java index 16aa81c9601..e4d5ea7f5d7 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java @@ -235,7 +235,7 @@ public static int testStub() { @Test public void test() { HotSpotProviders providers = (HotSpotProviders) getProviders(); - HotSpotForeignCallsProviderImpl foreignCalls = (HotSpotForeignCallsProviderImpl) providers.getForeignCalls(); + HotSpotForeignCallsProviderImpl foreignCalls = providers.getForeignCalls(); HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, HotSpotForeignCallDescriptor.Transition.LEAF_NO_VZERO, HotSpotForeignCallDescriptor.Reexecutability.REEXECUTABLE, COMPUTES_REGISTERS_KILLED); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java index 8e8cd772354..184a45a8475 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java @@ -331,6 +331,10 @@ public void emitCodeSuffix(ResolvedJavaMethod installedCodeOwner, CompilationRes AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), null, false, null); crb.recordMark(HotSpotMarkId.DEOPT_HANDLER_ENTRY); AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK), null, false, null); + if (config.supportsMethodHandleDeoptimizationEntry() && crb.needsMHDeoptHandler()) { + crb.recordMark(HotSpotMarkId.DEOPT_MH_HANDLER_ENTRY); + AMD64Call.directCall(crb, asm, foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK), null, false, null); + } } else { // No need to emit the stubs for entries back into the method since // it has no calls that can cause such "return" entries diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java index db5f47b7a8b..399844f4c37 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java @@ -58,7 +58,6 @@ import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.AddressLoweringPhase; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; -import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.amd64.AMD64GraphBuilderPlugins; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.compiler.serviceprovider.ServiceProvider; @@ -143,7 +142,7 @@ public HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRuntime, Co lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, platformConfigurationProvider, metaAccessExtensionProvider, target); } - Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, platformConfigurationProvider, + HotSpotProviders p = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider); try (InitTimer rt = timer("create SnippetReflection provider")) { @@ -164,7 +163,7 @@ public HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRuntime, Co suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, registers, replacements, options); } providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, - snippetReflection, wordTypes, plugins, platformConfigurationProvider, metaAccessExtensionProvider); + snippetReflection, wordTypes, plugins, platformConfigurationProvider, metaAccessExtensionProvider, config); replacements.setProviders(providers); replacements.maybeInitializeEncoder(options); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotDirectStaticCallOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotDirectStaticCallOp.java index 2afe2606f94..376e6aaae3d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotDirectStaticCallOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotDirectStaticCallOp.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot.amd64; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotMarkId; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.LIRInstructionClass; @@ -33,6 +34,7 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.Value; @@ -45,11 +47,13 @@ final class AMD64HotSpotDirectStaticCallOp extends DirectCallOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotDirectStaticCallOp.class); private final InvokeKind invokeKind; + private final GraalHotSpotVMConfig config; - AMD64HotSpotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind) { + AMD64HotSpotDirectStaticCallOp(ResolvedJavaMethod target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, GraalHotSpotVMConfig config) { super(TYPE, target, result, parameters, temps, state); assert invokeKind.isDirect(); this.invokeKind = invokeKind; + this.config = config; } @Override @@ -57,6 +61,9 @@ final class AMD64HotSpotDirectStaticCallOp extends DirectCallOp { public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { try (CompilationResultBuilder.CallContext callContext = crb.openCallContext(invokeKind.isDirect())) { crb.recordMark(invokeKind == InvokeKind.Static ? HotSpotMarkId.INVOKESTATIC : HotSpotMarkId.INVOKESPECIAL); + if (config.supportsMethodHandleDeoptimizationEntry() && config.isMethodHandleCall((HotSpotResolvedJavaMethod) callTarget) && invokeKind != InvokeKind.Static) { + crb.setNeedsMHDeoptHandler(); + } super.emitCode(crb, masm); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java index 54b2912dc37..579c367917d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.hotspot.amd64; +import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import org.graalvm.compiler.core.amd64.AMD64LoweringProviderMixin; @@ -70,10 +71,8 @@ public AMD64HotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAcc @Override public void initialize(OptionValues options, Iterable factories, HotSpotProviders providers, GraalHotSpotVMConfig config) { convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - if (JavaVersionUtil.JAVA_SPEC <= 8) { + if (JavaVersionUtil.JAVA_SPEC >= 11 && GeneratePIC.getValue(options)) { // AOT only introduced in JDK 9 - profileSnippets = null; - } else { profileSnippets = new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget()); } mathSnippets = new AMD64X87MathSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java index 14c949c117e..ef4a0d2ce0c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java @@ -142,7 +142,7 @@ protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Val assert invokeKind.isDirect(); HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); assert resolvedMethod.isConcrete() : "Cannot make direct call to abstract method."; - append(new AMD64HotSpotDirectStaticCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind)); + append(new AMD64HotSpotDirectStaticCallOp(callTarget.targetMethod(), result, parameters, temps, callState, invokeKind, getGen().config)); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java index 62d176d0ded..ac9396a3a29 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.Value; @@ -65,6 +66,9 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { crb.recordMark(invokeKind == InvokeKind.Virtual ? HotSpotMarkId.INVOKEVIRTUAL : HotSpotMarkId.INVOKEINTERFACE); // This must be emitted exactly like this to ensure it's patchable masm.movq(AMD64.rax, config.nonOopBits); + if (config.supportsMethodHandleDeoptimizationEntry() && config.isMethodHandleCall((HotSpotResolvedJavaMethod) callTarget)) { + crb.setNeedsMHDeoptHandler(); + } super.emitCall(crb, masm); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java index 2c008d9277a..4e283cc2ac9 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java @@ -378,8 +378,10 @@ public CheckGraalIntrinsics() { } if (isJDK10OrHigher()) { - add(toBeInvestigated, - "java/lang/Math.multiplyHigh(JJ)J"); + if (!(arch instanceof AArch64)) { + add(toBeInvestigated, + "java/lang/Math.multiplyHigh(JJ)J"); + } } if (isJDK11OrHigher()) { @@ -397,9 +399,12 @@ public CheckGraalIntrinsics() { } if (isJDK13OrHigher()) { + if (!(arch instanceof AArch64)) { + add(toBeInvestigated, + "java/lang/Math.abs(I)I", + "java/lang/Math.abs(J)J"); + } add(toBeInvestigated, - "java/lang/Math.abs(I)I", - "java/lang/Math.abs(J)J", "java/lang/Math.max(DD)D", "java/lang/Math.max(FF)F", "java/lang/Math.min(DD)D", diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java index 66bccbb8fc5..903e365ae0c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java @@ -1102,7 +1102,7 @@ static class Options { public static final OptionKey Config = new OptionKey<>(null); public static final OptionKey MultiThreaded = new OptionKey<>(false); public static final OptionKey Threads = new OptionKey<>(0); - public static final OptionKey InvalidateInstalledCode = new OptionKey<>(false); + public static final OptionKey InvalidateInstalledCode = new OptionKey<>(true); // @formatter:off static final ReflectionOptionDescriptors DESCRIPTORS = new ReflectionOptionDescriptors(Options.class, diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CommunityCompilerConfigurationFactory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CommunityCompilerConfigurationFactory.java index 781040bf288..4b2c326f6fe 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CommunityCompilerConfigurationFactory.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CommunityCompilerConfigurationFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot; import org.graalvm.compiler.core.phases.CommunityCompilerConfiguration; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.serviceprovider.ServiceProvider; @@ -50,4 +51,9 @@ public CommunityCompilerConfigurationFactory() { public CompilerConfiguration createCompilerConfiguration() { return new CommunityCompilerConfiguration(); } + + @Override + public Instrumentation createInstrumentation(OptionValues options) { + return new DefaultInstrumentation(); + } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java index 5bdb1d9d543..8d21b923f02 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,6 +96,8 @@ protected CompilerConfigurationFactory(String name, int autoSelectionPriority) { public abstract CompilerConfiguration createCompilerConfiguration(); + public abstract Instrumentation createInstrumentation(OptionValues options); + /** * Collect the set of available {@linkplain HotSpotBackendFactory backends} for this compiler * configuration. diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/DefaultInstrumentation.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/DefaultInstrumentation.java new file mode 100644 index 00000000000..aec18cc5489 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/DefaultInstrumentation.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.hotspot; + +/** + * Default version of {@link Instrumentation}. + */ +public class DefaultInstrumentation implements Instrumentation { +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EconomyCompilerConfigurationFactory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EconomyCompilerConfigurationFactory.java index 3c4305a9f1f..68a20a44896 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EconomyCompilerConfigurationFactory.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EconomyCompilerConfigurationFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot; import org.graalvm.compiler.core.phases.EconomyCompilerConfiguration; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.serviceprovider.ServiceProvider; @@ -52,4 +53,9 @@ public BackendMap createBackendMap() { // the economy configuration only differs in the frontend, it reuses the "community" backend return new DefaultBackendMap(CommunityCompilerConfigurationFactory.NAME); } + + @Override + public Instrumentation createInstrumentation(OptionValues options) { + return new DefaultInstrumentation(); + } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java index 39cd7fde992..a4d5ce88cf8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EncodedSnippets.java @@ -28,6 +28,8 @@ import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; +import java.util.function.Consumer; + import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap; import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; import org.graalvm.compiler.api.runtime.GraalRuntime; @@ -51,7 +53,6 @@ import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.ConstantBindingParameterPlugin; import org.graalvm.compiler.replacements.PEGraphDecoder; -import org.graalvm.compiler.replacements.ReplacementsImpl; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -61,52 +62,54 @@ import jdk.vm.ci.meta.UnresolvedJavaType; public class EncodedSnippets { + static class GraphData { + int startOffset; + String originalMethod; + + SnippetParameterInfo info; + + GraphData(int startOffset, String originalMethod, SnippetParameterInfo info) { + this.startOffset = startOffset; + this.originalMethod = originalMethod; + this.info = info; + } + } + private final byte[] snippetEncoding; private final Object[] snippetObjects; private final NodeClass[] snippetNodeClasses; - private final UnmodifiableEconomicMap snippetStartOffsets; - private final UnmodifiableEconomicMap originalMethods; - private UnmodifiableEconomicMap snippetParameterInfos; + private final UnmodifiableEconomicMap graphDatas; - EncodedSnippets(byte[] snippetEncoding, Object[] snippetObjects, NodeClass[] snippetNodeClasses, UnmodifiableEconomicMap snippetStartOffsets, - UnmodifiableEconomicMap originalMethods, UnmodifiableEconomicMap snippetParameterInfos) { + EncodedSnippets(byte[] snippetEncoding, Object[] snippetObjects, NodeClass[] snippetNodeClasses, UnmodifiableEconomicMap graphDatas) { this.snippetEncoding = snippetEncoding; this.snippetObjects = snippetObjects; this.snippetNodeClasses = snippetNodeClasses; - this.snippetStartOffsets = snippetStartOffsets; - this.originalMethods = originalMethods; - this.snippetParameterInfos = snippetParameterInfos; - } - - public byte[] getSnippetEncoding() { - return snippetEncoding; + this.graphDatas = graphDatas; } public NodeClass[] getSnippetNodeClasses() { return snippetNodeClasses; } - public UnmodifiableEconomicMap getSnippetStartOffsets() { - return snippetStartOffsets; + public void visitImmutable(Consumer visitor) { + visitor.accept(snippetEncoding); + visitor.accept(snippetNodeClasses); + visitor.accept(graphDatas); } - public UnmodifiableEconomicMap getOriginalMethods() { - return originalMethods; - } - - StructuredGraph getMethodSubstitutionGraph(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, ReplacementsImpl replacements, IntrinsicContext.CompilationContext context, + StructuredGraph getMethodSubstitutionGraph(MethodSubstitutionPlugin plugin, ResolvedJavaMethod original, HotSpotReplacementsImpl replacements, IntrinsicContext.CompilationContext context, StructuredGraph.AllowAssumptions allowAssumptions, Cancellable cancellable, OptionValues options) { IntrinsicContext.CompilationContext contextToUse = context; if (context == IntrinsicContext.CompilationContext.ROOT_COMPILATION) { contextToUse = IntrinsicContext.CompilationContext.ROOT_COMPILATION_ENCODING; } - Integer startOffset = snippetStartOffsets.get(plugin.toString() + contextToUse); - if (startOffset == null) { + GraphData data = graphDatas.get(plugin.toString() + contextToUse); + if (data == null) { throw GraalError.shouldNotReachHere("plugin graph not found: " + plugin + " with " + contextToUse); } ResolvedJavaType accessingClass = replacements.getProviders().getMetaAccess().lookupJavaType(plugin.getDeclaringClass()); - return decodeGraph(original, accessingClass, startOffset, replacements, contextToUse, allowAssumptions, cancellable, options); + return decodeGraph(original, accessingClass, data.startOffset, replacements, contextToUse, allowAssumptions, cancellable, options); } /** @@ -121,7 +124,7 @@ public static String methodKey(ResolvedJavaMethod method) { private StructuredGraph decodeGraph(ResolvedJavaMethod method, ResolvedJavaType accessingClass, int startOffset, - ReplacementsImpl replacements, + HotSpotReplacementsImpl replacements, IntrinsicContext.CompilationContext context, StructuredGraph.AllowAssumptions allowAssumptions, Cancellable cancellable, @@ -129,24 +132,23 @@ private StructuredGraph decodeGraph(ResolvedJavaMethod method, Providers providers = replacements.getProviders(); EncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, methodKey(method), accessingClass, method.getDeclaringClass()); - try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method, options)) { - boolean isSubstitution = true; - StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions).cancellable(cancellable).method(method).setIsSubstitution(isSubstitution).build(); - PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, null, method, context, encodedGraph); + try (DebugContext debug = replacements.openSnippetDebugContext("LibgraalSnippet_", method, options)) { + StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions).cancellable(cancellable).method(method).setIsSubstitution(true).build(); + PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, null, method, context, encodedGraph, true); - graphDecoder.decode(method, isSubstitution, encodedGraph.trackNodeSourcePosition()); + graphDecoder.decode(method, result.isSubstitution(), encodedGraph.trackNodeSourcePosition()); assert result.verify(); return result; } } - StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args, StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) { - Integer startOffset = null; - if (snippetStartOffsets != null) { - startOffset = snippetStartOffsets.get(methodKey(method)); + StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, HotSpotReplacementsImpl replacements, Object[] args, StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) { + GraphData data = null; + if (graphDatas != null) { + data = graphDatas.get(methodKey(method)); } - if (startOffset == null) { + if (data == null) { if (IS_IN_NATIVE_IMAGE) { throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); } else { @@ -154,31 +156,39 @@ StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ReplacementsImpl re } } - SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, - originalMethods.get(methodKey(method)), method.getDeclaringClass()); - return decodeSnippetGraph(encodedGraph, method, replacements, args, allowAssumptions, options); + SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, data.startOffset, snippetObjects, snippetNodeClasses, data.originalMethod, method.getDeclaringClass()); + return decodeSnippetGraph(encodedGraph, method, replacements, args, allowAssumptions, options, IS_IN_NATIVE_IMAGE); } public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) { - SnippetParameterInfo info = snippetParameterInfos.get(methodKey(method)); + GraphData data = null; + if (graphDatas != null) { + data = graphDatas.get(methodKey(method)); + } + assert data != null : method; + SnippetParameterInfo info = data.info; assert info != null; return info; } public boolean isSnippet(ResolvedJavaMethod method) { - return snippetParameterInfos.get(methodKey(method)) != null; + GraphData data = null; + if (graphDatas != null) { + data = graphDatas.get(methodKey(method)); + } + return data != null && data.info != null; } @SuppressWarnings("try") - private static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args, - StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) { + static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, ResolvedJavaMethod method, HotSpotReplacementsImpl replacements, Object[] args, + StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options, boolean mustSucceed) { Providers providers = replacements.getProviders(); ParameterPlugin parameterPlugin = null; if (args != null) { parameterPlugin = new ConstantBindingParameterPlugin(args, providers.getMetaAccess(), replacements.snippetReflection); } - try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method, options)) { + try (DebugContext debug = replacements.openSnippetDebugContext("SVMSnippet_", method, options)) { // @formatter:off boolean isSubstitution = true; StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions) @@ -188,7 +198,7 @@ private static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGr .build(); // @formatter:on try (DebugContext.Scope scope = debug.scope("DecodeSnippetGraph", result)) { - PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, parameterPlugin, method, INLINE_AFTER_PARSING, encodedGraph); + PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, parameterPlugin, method, INLINE_AFTER_PARSING, encodedGraph, mustSucceed); graphDecoder.decode(method, isSubstitution, encodedGraph.trackNodeSourcePosition()); debug.dump(DebugContext.VERBOSE_LEVEL, result, "After decoding"); @@ -201,18 +211,20 @@ private static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGr } } - public static class SubstitutionGraphDecoder extends PEGraphDecoder { + static class SubstitutionGraphDecoder extends PEGraphDecoder { private final ResolvedJavaMethod method; private final EncodedGraph encodedGraph; private IntrinsicContext intrinsic; + private final boolean mustSucceed; - SubstitutionGraphDecoder(Providers providers, StructuredGraph result, ReplacementsImpl replacements, ParameterPlugin parameterPlugin, ResolvedJavaMethod method, - IntrinsicContext.CompilationContext context, EncodedGraph encodedGraph) { + SubstitutionGraphDecoder(Providers providers, StructuredGraph result, HotSpotReplacementsImpl replacements, ParameterPlugin parameterPlugin, ResolvedJavaMethod method, + IntrinsicContext.CompilationContext context, EncodedGraph encodedGraph, boolean mustSucceed) { super(providers.getCodeCache().getTarget().arch, result, providers, null, replacements.getGraphBuilderPlugins().getInvocationPlugins(), new InlineInvokePlugin[0], parameterPlugin, null, null, null); this.method = method; this.encodedGraph = encodedGraph; + this.mustSucceed = mustSucceed; intrinsic = new IntrinsicContext(method, null, replacements.getDefaultReplacementBytecodeProvider(), context, false); } @@ -230,9 +242,14 @@ protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod lookupMethod, } @Override - protected IntrinsicContext getIntrinsic() { + public IntrinsicContext getIntrinsic() { return intrinsic; } + + @Override + protected boolean pluginReplacementMustSucceed() { + return mustSucceed; + } } static class SymbolicEncodedGraph extends EncodedGraph { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java index e7a77962d37..e0a7cf15cdb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java @@ -886,6 +886,7 @@ private boolean checkNullAllocationStubs() { public final int OSR_ENTRY = getConstant("CodeInstaller::OSR_ENTRY", Integer.class); public final int EXCEPTION_HANDLER_ENTRY = getConstant("CodeInstaller::EXCEPTION_HANDLER_ENTRY", Integer.class); public final int DEOPT_HANDLER_ENTRY = getConstant("CodeInstaller::DEOPT_HANDLER_ENTRY", Integer.class); + public final int DEOPT_MH_HANDLER_ENTRY = getConstant("CodeInstaller::DEOPT_MH_HANDLER_ENTRY", Integer.class, -1, (JVMCI ? jvmciGE(JVMCI_20_2_b01) : false)); public final int FRAME_COMPLETE = getConstant("CodeInstaller::FRAME_COMPLETE", Integer.class, -1, (JVMCI ? jvmciGE(JVMCI_20_1_b01) : JDK_8245443)); public final int INVOKEINTERFACE = getConstant("CodeInstaller::INVOKEINTERFACE", Integer.class); public final int INVOKEVIRTUAL = getConstant("CodeInstaller::INVOKEVIRTUAL", Integer.class); @@ -899,6 +900,10 @@ private boolean checkNullAllocationStubs() { public final int CARD_TABLE_SHIFT = getConstant("CodeInstaller::CARD_TABLE_SHIFT", Integer.class); public final int CARD_TABLE_ADDRESS = getConstant("CodeInstaller::CARD_TABLE_ADDRESS", Integer.class); public final int INVOKE_INVALID = getConstant("CodeInstaller::INVOKE_INVALID", Integer.class); + public final int VMINTRINSIC_FIRST_MH_SIG_POLY = getConstant("vmIntrinsics::FIRST_MH_SIG_POLY", Integer.class, -1, (JVMCI ? jvmciGE(JVMCI_20_2_b01) : false)); + public final int VMINTRINSIC_LAST_MH_SIG_POLY = getConstant("vmIntrinsics::LAST_MH_SIG_POLY", Integer.class, -1, (JVMCI ? jvmciGE(JVMCI_20_2_b01) : false)); + public final int VMINTRINSIC_INVOKE_GENERIC = getConstant("vmIntrinsics::_invokeGeneric", Integer.class, -1, (JVMCI ? jvmciGE(JVMCI_20_2_b01) : false)); + public final int VMINTRINSIC_COMPILED_LAMBDA_FORM = getConstant("vmIntrinsics::_compiledLambdaForm", Integer.class, -1, (JVMCI ? jvmciGE(JVMCI_20_2_b01) : false)); public final boolean CPU_HAS_INTEL_JCC_ERRATUM = getFieldValue("VM_Version::_has_intel_jcc_erratum", Boolean.class, "bool", true, "amd64".equals(osArch) && (JVMCI ? jvmciGE(JVMCI_20_1_b01) : JDK >= 15)); @@ -926,4 +931,17 @@ protected boolean check() { assert checkNullAllocationStubs(); return true; } + + public boolean isMethodHandleCall(HotSpotResolvedJavaMethod targetMethod) { + int intrinsicId = targetMethod.intrinsicId(); + return ((intrinsicId >= VMINTRINSIC_FIRST_MH_SIG_POLY && intrinsicId <= VMINTRINSIC_LAST_MH_SIG_POLY) // MethodHandles::is_signature_polymorphic + && intrinsicId != VMINTRINSIC_INVOKE_GENERIC) // MethodHandles::is_signature_polymorphic_intrinsic + || intrinsicId == VMINTRINSIC_COMPILED_LAMBDA_FORM; // ciMethod::is_compiled_lambda_form + } + + public boolean supportsMethodHandleDeoptimizationEntry() { + return DEOPT_MH_HANDLER_ENTRY != -1 && VMINTRINSIC_FIRST_MH_SIG_POLY != -1 && VMINTRINSIC_LAST_MH_SIG_POLY != -1 && VMINTRINSIC_INVOKE_GENERIC != -1 && + VMINTRINSIC_COMPILED_LAMBDA_FORM != -1; + } + } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigAccess.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigAccess.java index a247d7c79eb..409596857aa 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigAccess.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigAccess.java @@ -127,6 +127,7 @@ protected static String getProperty(String name) { public final String osArch; protected static final Version JVMCI_0_55 = new Version2(0, 55); + protected static final Version JVMCI_20_2_b01 = new Version3(20, 2, 1); protected static final Version JVMCI_20_1_b01 = new Version3(20, 1, 1); protected static final Version JVMCI_20_0_b03 = new Version3(20, 0, 3); protected static final Version JVMCI_19_3_b03 = new Version3(19, 3, 3); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java index 251240e6569..77a62edf099 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackendFactory.java @@ -26,13 +26,13 @@ import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider; +import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotMetaAccessExtensionProvider; import org.graalvm.compiler.hotspot.meta.HotSpotPlatformConfigurationProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSnippetReflectionProvider; import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; -import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider; import jdk.vm.ci.code.Architecture; @@ -64,7 +64,7 @@ protected HotSpotMetaAccessExtensionProvider createMetaAccessExtensionProvider() return new HotSpotMetaAccessExtensionProvider(); } - protected HotSpotReplacementsImpl createReplacements(TargetDescription target, Providers p, HotSpotSnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { + protected HotSpotReplacementsImpl createReplacements(TargetDescription target, HotSpotProviders p, HotSpotSnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, target); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java index 9a363196fc3..3e1917b23d8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java @@ -24,20 +24,22 @@ package org.graalvm.compiler.hotspot; -import static jdk.vm.ci.common.InitTimer.timer; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; -import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigAccess.JDK; - -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Supplier; - +import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.stack.StackIntrospection; +import jdk.vm.ci.common.InitTimer; +import jdk.vm.ci.hotspot.HotSpotCompilationRequest; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.hotspot.HotSpotVMConfigStore; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.runtime.JVMCI; +import jdk.vm.ci.runtime.JVMCIBackend; +import jdk.vm.ci.services.Services; import jdk.internal.vm.compiler.collections.EconomicMap; import jdk.internal.vm.compiler.collections.EconomicSet; import jdk.internal.vm.compiler.collections.Equivalence; @@ -78,22 +80,19 @@ import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.compiler.serviceprovider.GraalServices; -import jdk.vm.ci.code.Architecture; -import jdk.vm.ci.code.stack.StackIntrospection; -import jdk.vm.ci.common.InitTimer; -import jdk.vm.ci.hotspot.HotSpotCompilationRequest; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.hotspot.HotSpotVMConfigStore; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.runtime.JVMCI; -import jdk.vm.ci.runtime.JVMCIBackend; -import jdk.vm.ci.services.Services; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; + +import static jdk.vm.ci.common.InitTimer.timer; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; +import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigAccess.JDK; //JaCoCo Exclude @@ -138,6 +137,8 @@ public GlobalMetrics getMetricValues() { private final GraalHotSpotVMConfig config; + private final Instrumentation instrumentation; + /** * The options can be {@linkplain #setOptionValues(String[], String[]) updated} by external * interfaces such as JMX. This comes with the risk that inconsistencies can arise as an @@ -178,6 +179,8 @@ public GlobalMetrics getMetricValues() { CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration(); compilerConfigurationName = compilerConfigurationFactory.getName(); + this.instrumentation = compilerConfigurationFactory.createInstrumentation(options); + if (IS_AOT) { management = AOT_INJECTED_MANAGEMENT == null ? null : AOT_INJECTED_MANAGEMENT.get(); } else { @@ -427,6 +430,11 @@ public String getCompilerConfigurationName() { return compilerConfigurationName; } + @Override + public Instrumentation getInstrumentation() { + return instrumentation; + } + private long runtimeStartTime; /** @@ -492,7 +500,7 @@ synchronized void shutdown() { /** * Substituted by * {@code com.oracle.svm.graal.hotspot.libgraal.Target_org_graalvm_compiler_hotspot_HotSpotGraalRuntime} - * to call {@code org.graalvm.nativeimage.VMRuntime.shutdown()}. + * to call {@code jdk.internal.vm.compiler.nativeimage.VMRuntime.shutdown()}. */ private static void shutdownLibGraal() { } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java index 5748b22bfc8..c9d9fe98965 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java @@ -107,4 +107,9 @@ default String getName() { * which configuration is in use. */ String getCompilerConfigurationName(); + + /** + * Returns the instance holding the instrumentation data structures. + */ + Instrumentation getInstrumentation(); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java index 4140c912a9a..f03f8d25962 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java @@ -101,7 +101,7 @@ public HotSpotHostBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvid @SuppressWarnings("try") public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options) { final HotSpotProviders providers = getProviders(); - HotSpotHostForeignCallsProvider foreignCalls = (HotSpotHostForeignCallsProvider) providers.getForeignCalls(); + HotSpotHostForeignCallsProvider foreignCalls = providers.getForeignCalls(); final HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); try (InitTimer st = timer("foreignCalls.initialize")) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotMarkId.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotMarkId.java index bfb9e0f9c42..40f4fd3aafe 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotMarkId.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotMarkId.java @@ -42,6 +42,7 @@ public enum HotSpotMarkId implements CompilationResult.MarkId { OSR_ENTRY(false), EXCEPTION_HANDLER_ENTRY(false), DEOPT_HANDLER_ENTRY(false), + DEOPT_MH_HANDLER_ENTRY(false), FRAME_COMPLETE(true, true), INVOKEINTERFACE(false), INVOKEVIRTUAL(false), diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java index 775337d4289..54580e0a5ac 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java @@ -37,6 +37,7 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeSourcePosition; +import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotWordOperationPlugin; import org.graalvm.compiler.hotspot.word.HotSpotOperation; import org.graalvm.compiler.nodes.Cancellable; @@ -50,7 +51,6 @@ import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.spi.SnippetParameterInfo; import org.graalvm.compiler.options.OptionValues; -import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import org.graalvm.compiler.replacements.ReplacementsImpl; @@ -63,15 +63,20 @@ * them. */ public class HotSpotReplacementsImpl extends ReplacementsImpl { - public HotSpotReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { + public HotSpotReplacementsImpl(HotSpotProviders providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { super(new GraalDebugHandlersFactory(snippetReflection), providers, snippetReflection, bytecodeProvider, target); } - HotSpotReplacementsImpl(HotSpotReplacementsImpl replacements, Providers providers) { + HotSpotReplacementsImpl(HotSpotReplacementsImpl replacements, HotSpotProviders providers) { super(new GraalDebugHandlersFactory(replacements.snippetReflection), providers, replacements.snippetReflection, replacements.getDefaultReplacementBytecodeProvider(), replacements.target); } + @Override + public HotSpotProviders getProviders() { + return (HotSpotProviders) super.getProviders(); + } + public void maybeInitializeEncoder(OptionValues options) { if (IS_IN_NATIVE_IMAGE) { return; @@ -85,14 +90,6 @@ public void maybeInitializeEncoder(OptionValues options) { } } - /** - * Returns true if this Replacements is being used for preparation of snippets and substitutions - * for libgraal. - */ - public boolean isEncodingSnippets() { - return false; - } - @Override public Class getIntrinsifyingPlugin(ResolvedJavaMethod method) { if (!IS_IN_NATIVE_IMAGE) { @@ -189,6 +186,7 @@ public void notifyNotInlined(GraphBuilderContext b, ResolvedJavaMethod method, I @Override public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) { + assert method.isStatic() || receiver != null : "must have a constant type for the receiver"; if (!IS_IN_NATIVE_IMAGE) { assert !snippetRegistrationClosed : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)"); assert registeredSnippets.add(method) : "Cannot register snippet twice: " + method.format("%H.%n(%p)"); @@ -303,4 +301,12 @@ public StructuredGraph getMethodSubstitution(MethodSubstitutionPlugin plugin, Re return null; } + @SuppressWarnings("unchecked") + @Override + public T getInjectedArgument(Class capability) { + if (capability.equals(GraalHotSpotVMConfig.class)) { + return (T) getProviders().getConfig(); + } + return super.getInjectedArgument(capability); + } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/Instrumentation.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/Instrumentation.java new file mode 100644 index 00000000000..619353657ca --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/Instrumentation.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.hotspot; + +/** + * Interface in charge of holding the instrumentation data structures. + */ +public interface Instrumentation { +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java index c25b74b3f16..061ff25e514 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java @@ -43,7 +43,7 @@ */ public final class JVMCIVersionCheck { - private static final Version JVMCI_MIN_VERSION = new Version3(20, 1, 2); + private static final Version JVMCI_MIN_VERSION = new Version3(20, 2, 1); public interface Version { boolean isLessThan(Version other); @@ -180,6 +180,9 @@ public String toString() { } } + public static final String JVMCI8_RELEASES_URL = "https://github.com/graalvm/graal-jvmci-8/releases"; + public static final String JVMCI11_RELEASES_URL = "https://github.com/graalvm/labs-openjdk-11/releases"; + private void failVersionCheck(boolean exit, String reason, Object... args) { Formatter errorMessage = new Formatter().format(reason, args); String javaHome = props.get("java.home"); @@ -189,10 +192,10 @@ private void failVersionCheck(boolean exit, String reason, Object... args) { errorMessage.format("Currently used Java home directory is %s.%n", javaHome); errorMessage.format("Currently used VM configuration is: %s%n", vmName); if (javaSpecVersion.compareTo("1.9") < 0) { - errorMessage.format("Download the latest JVMCI JDK 8 from https://github.com/graalvm/openjdk8-jvmci-builder/releases"); + errorMessage.format("Download the latest JVMCI JDK 8 from " + JVMCI8_RELEASES_URL); } else { if (javaSpecVersion.compareTo("11") == 0 && vmVersion.contains("-jvmci-")) { - errorMessage.format("Download the latest Labs OpenJDK 11 from https://github.com/graalvm/labs-openjdk-11/releases"); + errorMessage.format("Download the latest Labs OpenJDK 11 from " + JVMCI11_RELEASES_URL); } else { errorMessage.format("Download JDK 11 or later."); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java index a210a721e3b..65491dc915a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java @@ -56,7 +56,6 @@ import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.hotspot.EncodedSnippets.GraalCapability; @@ -67,6 +66,7 @@ import org.graalvm.compiler.hotspot.EncodedSnippets.SymbolicStampPair; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.java.BytecodeParser; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodeinfo.Verbosity; @@ -90,17 +90,15 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; -import org.graalvm.compiler.nodes.graphbuilderconf.ParameterPlugin; import org.graalvm.compiler.nodes.java.AccessFieldNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.SnippetParameterInfo; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.util.Providers; -import org.graalvm.compiler.replacements.ConstantBindingParameterPlugin; -import org.graalvm.compiler.replacements.PEGraphDecoder; import org.graalvm.compiler.replacements.ReplacementsImpl; import org.graalvm.compiler.replacements.SnippetCounter; import org.graalvm.compiler.replacements.SnippetIntegerHistogram; @@ -149,11 +147,109 @@ public class SymbolicSnippetEncoder { */ private int encodedGraphs = 0; + abstract static class GraphKey { + final ResolvedJavaMethod method; + final ResolvedJavaMethod original; + + GraphKey(ResolvedJavaMethod method, ResolvedJavaMethod original) { + this.method = method; + this.original = original; + } + + public abstract String keyString(); + + } + + static class SnippetKey extends GraphKey { + + SnippetKey(ResolvedJavaMethod method, ResolvedJavaMethod original) { + super(method, original); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SnippetKey that = (SnippetKey) o; + return Objects.equals(method, that.method) && + Objects.equals(original, that.original); + } + + @Override + public int hashCode() { + return Objects.hash(method, original); + } + + @Override + public String keyString() { + return methodKey(method); + } + + @Override + public String toString() { + return "SnippetKey{" + + "method=" + method + + ", original=" + original + + '}'; + } + } + + static class MethodSubstitutionKey extends GraphKey { + final IntrinsicContext.CompilationContext context; + final MethodSubstitutionPlugin plugin; + + MethodSubstitutionKey(ResolvedJavaMethod method, ResolvedJavaMethod original, IntrinsicContext.CompilationContext context, MethodSubstitutionPlugin plugin) { + super(method, original); + this.context = context; + this.plugin = plugin; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MethodSubstitutionKey that = (MethodSubstitutionKey) o; + return Objects.equals(original, that.original) && + context == that.context && + Objects.equals(plugin, that.plugin); + } + + @Override + public int hashCode() { + return Objects.hash(original, context, plugin); + } + + @Override + public String keyString() { + return plugin.toString() + context; + } + + @Override + public String toString() { + return "MethodSubstitutionKey{" + + "method=" + method + + ", original=" + original + + ", context=" + context + + ", plugin=" + plugin + + '}'; + } + } + /** * All the graphs parsed so far. */ private EconomicMap preparedSnippetGraphs = EconomicMap.create(); + private EconomicMap keyToMethod = EconomicMap.create(); + private EconomicMap snippetParameterInfos = EconomicMap.create(); private EconomicSet knownPlugins = EconomicSet.create(); @@ -172,9 +268,8 @@ void addDelayedInvocationPluginMethod(ResolvedJavaMethod method) { } public void clearSnippetParameterNames() { - MapCursor cursor = snippetParameterInfos.getEntries(); - while (cursor.advance()) { - cursor.getValue().clearNames(); + for (SnippetParameterInfo info : snippetParameterInfos.getValues()) { + info.clearNames(); } } @@ -187,11 +282,6 @@ public InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod m return InlineInfo.DO_NOT_INLINE_NO_EXCEPTION; } - if (snippetReplacements.getIntrinsifyingPlugin(method) != null) { - delayedInvocationPluginMethods.add(method); - return InlineInfo.DO_NOT_INLINE_NO_EXCEPTION; - } - // Force inlining when parsing replacements return createIntrinsicInlineInfo(method, snippetReplacements.getDefaultReplacementBytecodeProvider()); } @@ -202,21 +292,6 @@ public void notifyAfterInline(ResolvedJavaMethod methodToInline) { } } - public static class SnippetInvocationPlugins extends InvocationPlugins { - - SnippetInvocationPlugins(InvocationPlugins invocationPlugins) { - super(invocationPlugins); - } - - @Override - public InvocationPlugin lookupInvocation(ResolvedJavaMethod method) { - if (method.getAnnotation(Fold.class) != null) { - return null; - } - return super.lookupInvocation(method); - } - } - /** * This plugin disables the snippet counter machinery. */ @@ -246,12 +321,12 @@ public boolean handleLoadField(GraphBuilderContext b, ValueNode object, Resolved SymbolicSnippetEncoder(HotSpotReplacementsImpl replacements) { this.originalReplacements = replacements; GraphBuilderConfiguration.Plugins plugins = replacements.getGraphBuilderPlugins(); - SnippetInvocationPlugins invocationPlugins = new SnippetInvocationPlugins(plugins.getInvocationPlugins()); + InvocationPlugins invocationPlugins = plugins.getInvocationPlugins(); GraphBuilderConfiguration.Plugins copy = new GraphBuilderConfiguration.Plugins(plugins, invocationPlugins); copy.clearInlineInvokePlugins(); copy.appendInlineInvokePlugin(new SnippetInlineInvokePlugin()); copy.appendNodePlugin(new SnippetCounterPlugin()); - HotSpotProviders providers = (HotSpotProviders) replacements.getProviders().copyWith(new HotSpotSubstrateConstantReflectionProvider(replacements.getProviders().getConstantReflection())); + HotSpotProviders providers = replacements.getProviders().copyWith(new HotSpotSubstrateConstantReflectionProvider(replacements.getProviders().getConstantReflection())); this.snippetReplacements = new HotSpotSnippetReplacementsImpl(replacements, providers.copyWith(copy)); this.snippetReplacements.setGraphBuilderPlugins(copy); } @@ -278,8 +353,10 @@ private synchronized void registerMethodSubstitution(MethodSubstitutionPlugin pl assert method.getAnnotation(MethodSubstitution.class) != null : "MethodSubstitution must be annotated with @" + MethodSubstitution.class.getSimpleName(); String originalMethodString = plugin.originalMethodAsString(); StructuredGraph subst = buildGraph(method, original, originalMethodString, null, true, false, context, options); - originalMethods.put(methodKey(method), originalMethodString); - preparedSnippetGraphs.put(plugin.toString() + context, subst); + MethodSubstitutionKey key = new MethodSubstitutionKey(method, original, context, plugin); + originalMethods.put(key.keyString(), originalMethodString); + preparedSnippetGraphs.put(key.keyString(), subst); + keyToMethod.put(key.keyString(), key); } private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod original, String originalMethodString, Object receiver, boolean requireInlining, boolean trackNodeSourcePosition, @@ -300,7 +377,7 @@ private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod if (context == IntrinsicContext.CompilationContext.ROOT_COMPILATION) { contextToUse = IntrinsicContext.CompilationContext.ROOT_COMPILATION_ENCODING; } - try (DebugContext debug = openDebugContext("SymbolicSnippetEncoder_", method, options)) { + try (DebugContext debug = snippetReplacements.openSnippetDebugContext("SymbolicSnippetEncoder_", method, options)) { StructuredGraph graph = snippetReplacements.makeGraph(debug, snippetReplacements.getDefaultReplacementBytecodeProvider(), method, args, original, trackNodeSourcePosition, null, contextToUse); @@ -311,51 +388,19 @@ private StructuredGraph buildGraph(ResolvedJavaMethod method, ResolvedJavaMethod throw GraalError.shouldNotReachHere("method " + callee.format("%H.%n") + " not inlined in snippet " + method.getName() + " (maybe not final?)"); } } - assert verifySnippetEncodeDecode(debug, method, original, originalMethodString, trackNodeSourcePosition, graph); + assert verifySnippetEncodeDecode(debug, method, original, originalMethodString, args, trackNodeSourcePosition, graph); debug.dump(DebugContext.VERBOSE_LEVEL, graph, "After buildGraph"); return graph; } } @SuppressWarnings("try") - private static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, ResolvedJavaMethod method, ReplacementsImpl replacements, Object[] args, - StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) { - Providers providers = replacements.getProviders(); - ParameterPlugin parameterPlugin = null; - if (args != null) { - parameterPlugin = new ConstantBindingParameterPlugin(args, providers.getMetaAccess(), replacements.snippetReflection); - } - - try (DebugContext debug = replacements.openDebugContext("SVMSnippet_", method, options)) { - // @formatter:off - boolean isSubstitution = true; - StructuredGraph result = new StructuredGraph.Builder(options, debug, allowAssumptions) - .method(method) - .trackNodeSourcePosition(encodedGraph.trackNodeSourcePosition()) - .setIsSubstitution(isSubstitution) - .build(); - // @formatter:on - try (DebugContext.Scope scope = debug.scope("DecodeSnippetGraph", result)) { - PEGraphDecoder graphDecoder = new EncodedSnippets.SubstitutionGraphDecoder(providers, result, replacements, parameterPlugin, method, INLINE_AFTER_PARSING, encodedGraph); - - graphDecoder.decode(method, isSubstitution, encodedGraph.trackNodeSourcePosition()); - debug.dump(DebugContext.VERBOSE_LEVEL, result, "After decoding"); - - assert result.verify(); - return result; - } catch (Throwable t) { - throw debug.handle(t); - } - } - } - - @SuppressWarnings("try") - private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod method, ResolvedJavaMethod original, String originalMethodString, boolean trackNodeSourcePosition, + private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod method, ResolvedJavaMethod original, String originalMethodString, Object[] args, boolean trackNodeSourcePosition, StructuredGraph graph) { // Verify the encoding and decoding process EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget().arch); - HotSpotProviders originalProvider = (HotSpotProviders) snippetReplacements.getProviders(); + HotSpotProviders originalProvider = snippetReplacements.getProviders(); SnippetReflectionProvider snippetReflection = originalProvider.getSnippetReflection(); SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider constantReflection = new SymbolicSnippetEncoder.HotSpotSubstrateConstantReflectionProvider( @@ -363,7 +408,7 @@ private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod HotSpotProviders newProviders = new HotSpotProviders(originalProvider.getMetaAccess(), originalProvider.getCodeCache(), constantReflection, originalProvider.getConstantFieldProvider(), originalProvider.getForeignCalls(), originalProvider.getLowerer(), null, originalProvider.getSuites(), originalProvider.getRegisters(), snippetReflection, originalProvider.getWordTypes(), originalProvider.getGraphBuilderPlugins(), - originalProvider.getPlatformConfigurationProvider(), originalProvider.getMetaAccessExtensionProvider()); + originalProvider.getPlatformConfigurationProvider(), originalProvider.getMetaAccessExtensionProvider(), originalProvider.getConfig()); HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(newProviders, snippetReflection, originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(), originalProvider.getCodeCache().getTarget()); filteringReplacements.setGraphBuilderPlugins(originalProvider.getReplacements().getGraphBuilderPlugins()); @@ -371,11 +416,11 @@ private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod for (int i = 0; i < encodedGraph.getNumObjects(); i++) { filterSnippetObject(encodedGraph.getObject(i)); } - StructuredGraph snippet = filteringReplacements.makeGraph(debug, filteringReplacements.getDefaultReplacementBytecodeProvider(), method, null, original, + StructuredGraph snippet = filteringReplacements.makeGraph(debug, filteringReplacements.getDefaultReplacementBytecodeProvider(), method, args, original, trackNodeSourcePosition, null); SymbolicEncodedGraph symbolicGraph = new SymbolicEncodedGraph(encodedGraph, method.getDeclaringClass(), originalMethodString); - StructuredGraph decodedSnippet = decodeSnippetGraph(symbolicGraph, original != null ? original : method, originalReplacements, null, - StructuredGraph.AllowAssumptions.ifNonNull(graph.getAssumptions()), graph.getOptions()); + StructuredGraph decodedSnippet = EncodedSnippets.decodeSnippetGraph(symbolicGraph, original != null ? original : method, originalReplacements, null, + StructuredGraph.AllowAssumptions.ifNonNull(graph.getAssumptions()), graph.getOptions(), false); String snippetString = getCanonicalGraphString(snippet, true, false); String decodedSnippetString = getCanonicalGraphString(decodedSnippet, true, false); if (snippetString.equals(decodedSnippetString)) { @@ -430,14 +475,16 @@ private synchronized EncodedSnippets maybeEncodeSnippets(OptionValues options) { synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) { if (IS_BUILDING_NATIVE_IMAGE || UseEncodedGraphs.getValue(options)) { assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); - String key = methodKey(method); - if (!preparedSnippetGraphs.containsKey(key)) { + SnippetKey key = new SnippetKey(method, original); + String keyString = key.keyString(); + if (!preparedSnippetGraphs.containsKey(keyString)) { if (original != null) { - originalMethods.put(key, methodKey(original)); + originalMethods.put(keyString, methodKey(original)); } StructuredGraph snippet = buildGraph(method, original, null, receiver, true, trackNodeSourcePosition, INLINE_AFTER_PARSING, options); - preparedSnippetGraphs.put(key, snippet); - snippetParameterInfos.put(key, new SnippetParameterInfo(method)); + preparedSnippetGraphs.put(keyString, snippet); + snippetParameterInfos.put(keyString, new SnippetParameterInfo(method)); + keyToMethod.put(keyString, key); } } @@ -450,26 +497,22 @@ private synchronized EncodedSnippets encodeSnippets(DebugContext debug) { } encoder.finishPrepare(); - byte[] snippetEncoding; - Object[] snippetObjects; - NodeClass[] snippetNodeClasses; - EconomicMap snippetStartOffsets; - - snippetStartOffsets = EconomicMap.create(); + EconomicMap graphDatas = EconomicMap.create(); MapCursor cursor = preparedSnippetGraphs.getEntries(); while (cursor.advance()) { - snippetStartOffsets.put(cursor.getKey(), encoder.encode(cursor.getValue())); + EncodedSnippets.GraphData data = new EncodedSnippets.GraphData(encoder.encode(cursor.getValue()), originalMethods.get(cursor.getKey()), snippetParameterInfos.get(cursor.getKey())); + graphDatas.put(cursor.getKey(), data); } - snippetEncoding = encoder.getEncoding(); - snippetObjects = encoder.getObjects(); - snippetNodeClasses = encoder.getNodeClasses(); + + byte[] snippetEncoding = encoder.getEncoding(); + Object[] snippetObjects = encoder.getObjects(); for (int i = 0; i < snippetObjects.length; i++) { Object o = filterSnippetObject(snippetObjects[i]); debug.log("snippetObjects[%d] = %s -> %s", i, o != null ? o.getClass().getSimpleName() : null, o); snippetObjects[i] = o; } - debug.log("Encoded %d snippet preparedSnippetGraphs using %d bytes with %d objects", snippetStartOffsets.size(), snippetEncoding.length, snippetObjects.length); - return new EncodedSnippets(snippetEncoding, snippetObjects, snippetNodeClasses, snippetStartOffsets, originalMethods, snippetParameterInfos); + debug.log("Encoded %d snippet preparedSnippetGraphs using %d bytes with %d objects", graphDatas.size(), snippetEncoding.length, snippetObjects.length); + return new EncodedSnippets(snippetEncoding, snippetObjects, encoder.getNodeClasses(), graphDatas); } /** @@ -594,7 +637,8 @@ private static Object filterSnippetObject(Object o) { // Filter these out for now. These can't easily be handled because these positions // description snippet methods which might not be available in the runtime. return null; - } else if (o instanceof HotSpotForeignCallsProvider || o instanceof GraalHotSpotVMConfig) { + } else if (o instanceof HotSpotForeignCallsProvider || o instanceof GraalHotSpotVMConfig || o instanceof HotSpotWordTypes || o instanceof TargetDescription || + o instanceof SnippetReflectionProvider) { return new GraalCapability(o.getClass()); } else if (o instanceof Stamp) { SymbolicJVMCIReference ref = ((Stamp) o).makeSymbolic(); @@ -731,11 +775,11 @@ private static int filteredUsageCount(Node node) { * as the parser for these snippets. */ class HotSpotSnippetReplacementsImpl extends HotSpotReplacementsImpl { - HotSpotSnippetReplacementsImpl(HotSpotReplacementsImpl replacements, Providers providers) { + HotSpotSnippetReplacementsImpl(HotSpotReplacementsImpl replacements, HotSpotProviders providers) { super(replacements, providers); } - HotSpotSnippetReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { + HotSpotSnippetReplacementsImpl(HotSpotProviders providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { super(providers, snippetReflection, bytecodeProvider, target); } @@ -764,7 +808,7 @@ protected GraphBuilderPhase.Instance createGraphBuilder(Providers providers, Gra } class HotSpotSnippetGraphBuilderPhase extends GraphBuilderPhase.Instance { - HotSpotSnippetGraphBuilderPhase(Providers theProviders, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { + HotSpotSnippetGraphBuilderPhase(CoreProviders theProviders, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts, IntrinsicContext initialIntrinsicContext) { super(theProviders, graphBuilderConfig, optimisticOpts, initialIntrinsicContext); } @@ -787,6 +831,11 @@ public boolean canDeferPlugin(GeneratedInvocationPlugin plugin) { return plugin.isGeneratedFromFoldOrNodeIntrinsic(); } + @Override + public boolean shouldDeferPlugin(GeneratedInvocationPlugin plugin) { + return plugin.isGeneratedFromFoldOrNodeIntrinsic(); + } + @Override protected boolean canInlinePartialIntrinsicExit() { return false; @@ -797,10 +846,7 @@ protected boolean tryInvocationPlugin(CallTargetNode.InvokeKind invokeKind, Valu if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) { return false; } - if (targetMethod.getAnnotation(Fold.class) != null) { - // Always defer Fold until decode time but NodeIntrinsics may fold if they are able. - return false; - } + InvocationPlugin plugin = graphBuilderConfig.getPlugins().getInvocationPlugins().lookupInvocation(targetMethod); if (plugin != null && conditionalPlugins.contains(plugin)) { // Because supporting arbitrary plugins in the context of encoded graphs is complex diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java index bb7cd9713d3..c12a42baab5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java @@ -26,6 +26,7 @@ import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; import static org.graalvm.compiler.core.common.GraalOptions.AlwaysInlineVTableStubs; +import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.InlineVTableStubs; import static org.graalvm.compiler.core.common.GraalOptions.OmitHotExceptionStacktrace; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END; @@ -229,7 +230,7 @@ public void initialize(OptionValues options, Iterable fact allocationSnippets = new HotSpotAllocationSnippets.Templates(options, factories, runtime, providers, target, config); monitorSnippets = new MonitorSnippets.Templates(options, factories, runtime, providers, target, config.useFastLocking); g1WriteBarrierSnippets = new HotSpotG1WriteBarrierSnippets.Templates(options, factories, runtime, providers, target, config); - serialWriteBarrierSnippets = new HotSpotSerialWriteBarrierSnippets.Templates(options, factories, runtime, providers, target, config); + serialWriteBarrierSnippets = new HotSpotSerialWriteBarrierSnippets.Templates(options, factories, runtime, providers, target); exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(options, factories, providers, target); assertionSnippets = new AssertionSnippets.Templates(options, factories, providers, target); arraycopySnippets = new ArrayCopySnippets.Templates(new HotSpotArraycopySnippets(), options, factories, runtime, providers, providers.getSnippetReflection(), target); @@ -238,12 +239,12 @@ public void initialize(OptionValues options, Iterable fact resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, factories, providers, target); objectCloneSnippets = new ObjectCloneSnippets.Templates(options, factories, providers, target); foreignCallSnippets = new ForeignCallSnippets.Templates(options, factories, providers, target); - objectSnippets = new ObjectSnippets.Templates(options, factories, providers, target); + if (JavaVersionUtil.JAVA_SPEC >= 11) { + objectSnippets = new ObjectSnippets.Templates(options, factories, providers, target); + } unsafeSnippets = new UnsafeSnippets.Templates(options, factories, providers, target); - if (JavaVersionUtil.JAVA_SPEC <= 8) { + if (JavaVersionUtil.JAVA_SPEC >= 11 && GeneratePIC.getValue(options)) { // AOT only introduced in JDK 9 - profileSnippets = null; - } else { profileSnippets = new ProfileSnippets.Templates(options, factories, providers, target); } } @@ -419,6 +420,9 @@ public void lower(Node n, LoweringTool tool) { } else if (n instanceof KlassBeingInitializedCheckNode) { allocationSnippets.lower((KlassBeingInitializedCheckNode) n, tool); } else if (n instanceof FastNotifyNode) { + if (JavaVersionUtil.JAVA_SPEC < 11) { + throw GraalError.shouldNotReachHere("FastNotify is not support prior to 11"); + } if (graph.getGuardsStage() == GuardsStage.AFTER_FSA) { objectSnippets.lower(n, tool); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java index 50ff33faf47..e417df2315b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java @@ -179,14 +179,15 @@ public void linkForeignCall(OptionValues options, HotSpotForeignCallDescriptor descriptor, long address, boolean prependThread) { - if (address != 0) { - ForeignCallStub stub = new ForeignCallStub(options, jvmciRuntime, providers, address, descriptor, prependThread); - HotSpotForeignCallLinkage linkage = stub.getLinkage(); - HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage(); - linkage.setCompiledStub(stub); - register(linkage); - register(targetLinkage); + if (address == 0) { + throw new IllegalArgumentException("Can't link foreign call with zero address"); } + ForeignCallStub stub = new ForeignCallStub(options, jvmciRuntime, providers, address, descriptor, prependThread); + HotSpotForeignCallLinkage linkage = stub.getLinkage(); + HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage(); + linkage.setCompiledStub(stub); + register(linkage); + register(targetLinkage); } public static final boolean PREPEND_THREAD = true; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index 02bca74d8db..bfef259ea93 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -84,13 +84,13 @@ import org.graalvm.compiler.nodes.calc.LeftShiftNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.graphbuilderconf.ForeignCallPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginFactory; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; -import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory; import org.graalvm.compiler.nodes.java.DynamicNewInstanceNode; import org.graalvm.compiler.nodes.memory.OnHeapMemoryAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; @@ -152,8 +152,8 @@ public static Plugins create(HotSpotGraalRuntimeProvider graalRuntime, InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(graalRuntime, config, compilerConfiguration); Plugins plugins = new Plugins(invocationPlugins); - NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes, target); if (!IS_IN_NATIVE_IMAGE) { + // In libgraal all word related operations have been fully processed so this is unneeded HotSpotWordOperationPlugin wordOperationPlugin = new HotSpotWordOperationPlugin(snippetReflection, wordTypes); HotSpotNodePlugin nodePlugin = new HotSpotNodePlugin(wordOperationPlugin, config, wordTypes); @@ -161,7 +161,7 @@ public static Plugins create(HotSpotGraalRuntimeProvider graalRuntime, plugins.appendNodePlugin(nodePlugin); } if (!GeneratePIC.getValue(options)) { - plugins.appendNodePlugin(new MethodHandlePlugin(constantReflection.getMethodHandleAccess(), true)); + plugins.appendNodePlugin(new MethodHandlePlugin(constantReflection.getMethodHandleAccess(), !config.supportsMethodHandleDeoptimizationEntry())); } plugins.appendInlineInvokePlugin(replacements); if (InlineDuringParsing.getValue(options)) { @@ -205,12 +205,24 @@ public void run() { registerArrayPlugins(invocationPlugins, replacements); registerStringPlugins(invocationPlugins, replacements); registerArraysSupportPlugins(invocationPlugins, config, replacements); - - for (NodeIntrinsicPluginFactory factory : GraalServices.load(NodeIntrinsicPluginFactory.class)) { - factory.registerPlugins(invocationPlugins, nodeIntrinsificationProvider); - } } }); + if (!IS_IN_NATIVE_IMAGE) { + // In libgraal all NodeIntrinsics been converted into special nodes so the plugins + // aren't needed. + NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes, target); + invocationPlugins.defer(new Runnable() { + + @Override + public void run() { + + for (GeneratedPluginFactory factory : GraalServices.load(GeneratedPluginFactory.class)) { + factory.registerPlugins(invocationPlugins, nodeIntrinsificationProvider); + } + + } + }); + } return plugins; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index 8d711426e82..716485cbc80 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -128,6 +128,7 @@ import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode.BytecodeExceptionKind; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.arraycopy.ArrayCopyForeignCalls; +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordTypes; import jdk.internal.vm.compiler.word.LocationIdentity; @@ -361,8 +362,12 @@ public void initialize(HotSpotProviders providers, OptionValues options) { linkForeignCall(options, providers, createDescriptor(REGISTER_FINALIZER, SAFEPOINT, NOT_REEXECUTABLE, any()), c.registerFinalizerAddress, PREPEND_THREAD); linkForeignCall(options, providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD); linkForeignCall(options, providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD); - linkForeignCall(options, providers, NOTIFY, c.notifyAddress, PREPEND_THREAD); - linkForeignCall(options, providers, NOTIFY_ALL, c.notifyAllAddress, PREPEND_THREAD); + if (JavaVersionUtil.JAVA_SPEC >= 11) { + linkForeignCall(options, providers, NOTIFY, c.notifyAddress, PREPEND_THREAD); + linkForeignCall(options, providers, NOTIFY_ALL, c.notifyAllAddress, PREPEND_THREAD); + } else { + assert c.notifyAddress == 0 : "unexpected value"; + } linkForeignCall(options, providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD); linkForeignCall(options, providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD); linkForeignCall(options, providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java index 580e87e6ed8..827e8502d9d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java @@ -26,14 +26,19 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; +import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.spi.MetaAccessExtensionProvider; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.spi.LoweringProvider; +import org.graalvm.compiler.nodes.spi.PlatformConfigurationProvider; import org.graalvm.compiler.nodes.spi.Replacements; +import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.phases.tiers.SuitesProvider; import org.graalvm.compiler.phases.util.Providers; +import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; @@ -46,20 +51,40 @@ public class HotSpotProviders extends Providers { private final SuitesProvider suites; private final HotSpotRegistersProvider registers; - private final SnippetReflectionProvider snippetReflection; - private final HotSpotWordTypes wordTypes; private final Plugins graphBuilderPlugins; - - public HotSpotProviders(MetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantField, - HotSpotForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, SuitesProvider suites, HotSpotRegistersProvider registers, - SnippetReflectionProvider snippetReflection, HotSpotWordTypes wordTypes, Plugins graphBuilderPlugins, HotSpotPlatformConfigurationProvider platformConfigurationProvider, - MetaAccessExtensionProvider metaAccessExtensionProvider) { - super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, new HotSpotStampProvider(), platformConfigurationProvider, metaAccessExtensionProvider); + private final GraalHotSpotVMConfig config; + + public HotSpotProviders(MetaAccessProvider metaAccess, + HotSpotCodeCacheProvider codeCache, + ConstantReflectionProvider constantReflection, + ConstantFieldProvider constantField, + HotSpotHostForeignCallsProvider foreignCalls, + LoweringProvider lowerer, + Replacements replacements, + SuitesProvider suites, + HotSpotRegistersProvider registers, + SnippetReflectionProvider snippetReflection, + HotSpotWordTypes wordTypes, + Plugins graphBuilderPlugins, + PlatformConfigurationProvider platformConfigurationProvider, + MetaAccessExtensionProvider metaAccessExtensionProvider, + GraalHotSpotVMConfig config) { + super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, new HotSpotStampProvider(), platformConfigurationProvider, metaAccessExtensionProvider, + snippetReflection, wordTypes); this.suites = suites; this.registers = registers; - this.snippetReflection = snippetReflection; - this.wordTypes = wordTypes; this.graphBuilderPlugins = graphBuilderPlugins; + this.config = config; + } + + public HotSpotProviders(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantField, + ForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, PlatformConfigurationProvider platformConfigurationProvider, + MetaAccessExtensionProvider metaAccessExtensionProvider) { + super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, null, null); + this.suites = null; + this.registers = null; + this.graphBuilderPlugins = null; + this.config = null; } @Override @@ -68,8 +93,8 @@ public HotSpotCodeCacheProvider getCodeCache() { } @Override - public HotSpotForeignCallsProvider getForeignCalls() { - return (HotSpotForeignCallsProvider) super.getForeignCalls(); + public HotSpotHostForeignCallsProvider getForeignCalls() { + return (HotSpotHostForeignCallsProvider) super.getForeignCalls(); } public SuitesProvider getSuites() { @@ -80,47 +105,46 @@ public HotSpotRegistersProvider getRegisters() { return registers; } - public SnippetReflectionProvider getSnippetReflection() { - return snippetReflection; - } - public Plugins getGraphBuilderPlugins() { return graphBuilderPlugins; } + @Override public HotSpotWordTypes getWordTypes() { - return wordTypes; + return (HotSpotWordTypes) super.getWordTypes(); + } + + public GraalHotSpotVMConfig getConfig() { + return config; } @Override public HotSpotPlatformConfigurationProvider getPlatformConfigurationProvider() { - return (HotSpotPlatformConfigurationProvider) super.getPlatformConfigurationProvider(); + return (HotSpotPlatformConfigurationProvider) platformConfigurationProvider; } @Override - public Providers copyWith(ConstantReflectionProvider substitution) { - assert this.getClass() == HotSpotProviders.class : "must override in " + getClass(); + public HotSpotProviders copyWith(ConstantReflectionProvider substitution) { return new HotSpotProviders(getMetaAccess(), getCodeCache(), substitution, getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(), - getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider()); + getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), config); } @Override - public Providers copyWith(ConstantFieldProvider substitution) { - assert this.getClass() == HotSpotProviders.class : "must override in " + getClass(); - return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), substitution, getForeignCalls(), getLowerer(), getReplacements(), getSuites(), - getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider()); + public HotSpotProviders copyWith(ConstantFieldProvider substitution) { + return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), substitution, getForeignCalls(), getLowerer(), getReplacements(), + getSuites(), + getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), config); } @Override - public Providers copyWith(Replacements substitution) { - assert this.getClass() == HotSpotProviders.class : "must override in " + getClass(); - return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), substitution, getSuites(), - getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider()); + public HotSpotProviders copyWith(Replacements substitution) { + return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), substitution, + getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getGraphBuilderPlugins(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), config); } - public Providers copyWith(Plugins substitution) { - assert this.getClass() == HotSpotProviders.class : "must override in " + getClass(); - return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(), - getRegisters(), getSnippetReflection(), getWordTypes(), substitution, getPlatformConfigurationProvider(), getMetaAccessExtensionProvider()); + public HotSpotProviders copyWith(Plugins substitution) { + return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), + getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), substitution, getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), config); } + } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java index 79f28e60d50..0695becec66 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java @@ -32,13 +32,13 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotMarkId; -import org.graalvm.compiler.hotspot.HotSpotReplacementsImpl; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.calc.FloatingNode; @@ -47,13 +47,13 @@ import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.Value; /** * Represents {@link GraalHotSpotVMConfig} values that may change after compilation. */ @NodeInfo(cycles = CYCLES_1, size = SIZE_1) +@NodeIntrinsicFactory public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerable, Canonicalizable { public static final NodeClass TYPE = NodeClass.create(GraalHotSpotVMConfigNode.class); @@ -109,11 +109,8 @@ public static int logOfHeapRegionGrainBytes() { return loadIntConfigValue(HotSpotMarkId.LOG_OF_HEAP_REGION_GRAIN_BYTES); } - @SuppressWarnings("unused") - public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, @InjectedNodeParameter Stamp returnStamp, @InjectedNodeParameter GraalHotSpotVMConfig config, - HotSpotMarkId mark) { - HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) b.getReplacements(); - if (replacements.isEncodingSnippets()) { + public static boolean intrinsify(GraphBuilderContext b, @InjectedNodeParameter Stamp returnStamp, @InjectedNodeParameter GraalHotSpotVMConfig config, HotSpotMarkId mark) { + if (b.getReplacements().isEncodingSnippets()) { // This plugin must be deferred so that these constants aren't embedded in libgraal return false; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java index bcf14667a8a..d8ae146dc5e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java @@ -30,6 +30,7 @@ import org.graalvm.compiler.core.common.calc.CanonicalCondition; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; @@ -56,7 +57,6 @@ import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; /** @@ -66,6 +66,7 @@ * {@link ReadNode#canonicalizeRead(ValueNode, AddressNode, LocationIdentity, CanonicalizerTool)}. */ @NodeInfo(cycles = CYCLES_1, size = SIZE_1) +@NodeIntrinsicFactory public final class ClassGetHubNode extends FloatingNode implements Lowerable, Canonicalizable, ConvertNode { public static final NodeClass TYPE = NodeClass.create(ClassGetHubNode.class); @Input protected ValueNode clazz; @@ -79,8 +80,7 @@ public static ValueNode create(ValueNode clazz, MetaAccessProvider metaAccess, C return canonical(null, metaAccess, constantReflection, allUsagesAvailable, KlassPointerStamp.klass(), clazz); } - @SuppressWarnings("unused") - public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode clazz) { + public static boolean intrinsify(GraphBuilderContext b, ValueNode clazz) { ValueNode clazzValue = create(clazz, b.getMetaAccess(), b.getConstantReflection(), false); b.push(JavaKind.Object, b.append(clazzValue)); return true; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotAllocationSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotAllocationSnippets.java index 4ae2a9aea0e..99c445a3b6b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotAllocationSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotAllocationSnippets.java @@ -151,7 +151,7 @@ protected Object allocateInstance(KlassPointer hub, @ConstantParameter long size, @ConstantParameter boolean fillContents, @ConstantParameter boolean emitMemoryBarrier, - @ConstantParameter AllocationProfilingData profilingData) { + @ConstantParameter HotSpotAllocationProfilingData profilingData) { Object result = allocateInstanceImpl(hub.asWord(), prototypeMarkWord, WordFactory.unsigned(size), fillContents, emitMemoryBarrier, true, profilingData); return piCastToSnippetReplaceeStamp(result); } @@ -166,7 +166,7 @@ public Object allocateArray(KlassPointer hub, @ConstantParameter boolean emitMemoryBarrier, @ConstantParameter boolean maybeUnroll, @ConstantParameter boolean supportsBulkZeroing, - @ConstantParameter AllocationProfilingData profilingData) { + @ConstantParameter HotSpotAllocationProfilingData profilingData) { Object result = allocateArrayImpl(hub.asWord(), prototypeMarkWord, length, headerSize, log2ElementSize, fillContents, headerSize, emitMemoryBarrier, maybeUnroll, supportsBulkZeroing, profilingData); return piArrayCastToSnippetReplaceeStamp(result, length); @@ -178,7 +178,7 @@ protected Object allocateInstancePIC(KlassPointer hub, @ConstantParameter long size, @ConstantParameter boolean fillContents, @ConstantParameter boolean emitMemoryBarrier, - @ConstantParameter AllocationProfilingData profilingData) { + @ConstantParameter HotSpotAllocationProfilingData profilingData) { // Klass must be initialized by the time the first instance is allocated, therefore we can // just load it from the corresponding cell and avoid the resolution check. We have to use a // fixed load though, to prevent it from floating above the initialization. @@ -192,7 +192,7 @@ public Object allocateInstanceDynamic(Class type, Class classClass, @ConstantParameter boolean fillContents, @ConstantParameter boolean emitMemoryBarrier, - @ConstantParameter AllocationProfilingData profilingData) { + @ConstantParameter HotSpotAllocationProfilingData profilingData) { if (probability(DEOPT_PROBABILITY, type == null)) { DeoptimizeNode.deopt(None, RuntimeConstraint); } @@ -240,7 +240,7 @@ public Object allocatePrimitiveArrayPIC(KlassPointer hub, @ConstantParameter boolean emitMemoryBarrier, @ConstantParameter boolean maybeUnroll, @ConstantParameter boolean supportsBulkZeroing, - @ConstantParameter AllocationProfilingData profilingData) { + @ConstantParameter HotSpotAllocationProfilingData profilingData) { // Primitive array types are eagerly pre-resolved. We can use a floating load. KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub); return allocateArrayImpl(picHub.asWord(), prototypeMarkWord, length, headerSize, log2ElementSize, fillContents, headerSize, emitMemoryBarrier, maybeUnroll, supportsBulkZeroing, profilingData); @@ -256,7 +256,7 @@ public Object allocateArrayPIC(KlassPointer hub, @ConstantParameter boolean emitMemoryBarrier, @ConstantParameter boolean maybeUnroll, @ConstantParameter boolean supportsBulkZeroing, - @ConstantParameter AllocationProfilingData profilingData) { + @ConstantParameter HotSpotAllocationProfilingData profilingData) { // Array type would be resolved by dominating resolution. KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub); return allocateArrayImpl(picHub.asWord(), prototypeMarkWord, length, headerSize, log2ElementSize, fillContents, headerSize, emitMemoryBarrier, maybeUnroll, supportsBulkZeroing, profilingData); @@ -272,7 +272,7 @@ public Object allocateArrayDynamic(Class elementType, @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, @ConstantParameter boolean supportsBulkZeroing, - @ConstantParameter AllocationProfilingData profilingData) { + @ConstantParameter HotSpotAllocationProfilingData profilingData) { /* * We only need the dynamic check for void when we have no static information from * knownElementKind. @@ -637,7 +637,7 @@ public Templates(OptionValues options, Iterable factories, threadBeingInitializedCheck = snippet(HotSpotAllocationSnippets.class, "threadBeingInitializedCheck", null, receiver); } - private AllocationProfilingData getProfilingData(OptionValues localOptions, String path, ResolvedJavaType type) { + private HotSpotAllocationProfilingData getProfilingData(OptionValues localOptions, String path, ResolvedJavaType type) { if (ProfileAllocations.getValue(localOptions)) { // Create one object per snippet instantiation - this kills the snippet caching as // we need to add the object as a constant to the snippet. diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java index 0178ca4c802..a4445abe565 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotG1WriteBarrierSnippets.java @@ -55,6 +55,7 @@ import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.gc.G1WriteBarrierSnippets; import org.graalvm.compiler.word.Word; +import jdk.internal.vm.compiler.word.Pointer; import jdk.internal.vm.compiler.word.WordFactory; import jdk.vm.ci.code.Register; @@ -68,11 +69,9 @@ public final class HotSpotG1WriteBarrierSnippets extends G1WriteBarrierSnippets public static final HotSpotForeignCallDescriptor VALIDATE_OBJECT = new HotSpotForeignCallDescriptor(LEAF_NO_VZERO, REEXECUTABLE, NO_LOCATIONS, "validate_object", boolean.class, Word.class, Word.class); - private final GraalHotSpotVMConfig config; private final Register threadRegister; - public HotSpotG1WriteBarrierSnippets(GraalHotSpotVMConfig config, HotSpotRegistersProvider registers) { - this.config = config; + public HotSpotG1WriteBarrierSnippets(HotSpotRegistersProvider registers) { this.threadRegister = registers.getThreadRegister(); } @@ -127,13 +126,10 @@ protected byte youngCardValue() { } @Override - protected Word cardTableAddress() { - return WordFactory.unsigned(GraalHotSpotVMConfigNode.cardTableAddress()); - } - - @Override - protected int cardTableShift() { - return HotSpotReplacementsUtil.cardTableShift(INJECTED_VMCONFIG); + protected Word cardTableAddress(Pointer oop) { + Word cardTable = WordFactory.unsigned(GraalHotSpotVMConfigNode.cardTableAddress()); + int cardTableShift = HotSpotReplacementsUtil.cardTableShift(INJECTED_VMCONFIG); + return cardTable.add(oop.unsignedShiftRight(cardTableShift)); } @Override @@ -158,7 +154,7 @@ protected boolean verifyOops() { @Override protected boolean verifyBarrier() { - return ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED || config.verifyBeforeGC || config.verifyAfterGC; + return ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED || HotSpotReplacementsUtil.verifyBeforeOrAfterGC(INJECTED_VMCONFIG); } @Override @@ -204,7 +200,7 @@ public Templates(OptionValues options, Iterable factories, super(options, factories, providers, providers.getSnippetReflection(), target); this.lowerer = new HotspotG1WriteBarrierLowerer(config, factory); - HotSpotG1WriteBarrierSnippets receiver = new HotSpotG1WriteBarrierSnippets(config, providers.getRegisters()); + HotSpotG1WriteBarrierSnippets receiver = new HotSpotG1WriteBarrierSnippets(providers.getRegisters()); g1PreWriteBarrier = snippet(G1WriteBarrierSnippets.class, "g1PreWriteBarrier", null, receiver, GC_INDEX_LOCATION, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION, SATB_QUEUE_INDEX_LOCATION, SATB_QUEUE_BUFFER_LOCATION); g1ReferentReadBarrier = snippet(G1WriteBarrierSnippets.class, "g1ReferentReadBarrier", null, receiver, GC_INDEX_LOCATION, GC_LOG_LOCATION, SATB_QUEUE_MARKING_LOCATION, diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java index 4cc503912a2..e0a1f7e0c8b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java @@ -605,6 +605,11 @@ public static Word arrayStart(int[] a) { return WordFactory.unsigned(ComputeObjectAddressNode.get(a, ReplacementsUtil.getArrayBaseOffset(INJECTED_METAACCESS, JavaKind.Int))); } + @Fold + public static boolean verifyBeforeOrAfterGC(@InjectedParameter GraalHotSpotVMConfig config) { + return config.verifyBeforeGC || config.verifyAfterGC; + } + /** * Idiom for making {@link GraalHotSpotVMConfig} a constant. */ diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotSerialWriteBarrierSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotSerialWriteBarrierSnippets.java index 734584fc9d4..d404ac94866 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotSerialWriteBarrierSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotSerialWriteBarrierSnippets.java @@ -27,7 +27,6 @@ import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import org.graalvm.compiler.debug.DebugHandlersFactory; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; import org.graalvm.compiler.nodes.gc.SerialArrayRangeWriteBarrier; @@ -45,10 +44,8 @@ import jdk.vm.ci.code.TargetDescription; public class HotSpotSerialWriteBarrierSnippets extends SerialWriteBarrierSnippets { - private final GraalHotSpotVMConfig config; - public HotSpotSerialWriteBarrierSnippets(GraalHotSpotVMConfig config) { - this.config = config; + public HotSpotSerialWriteBarrierSnippets() { } @Override @@ -63,12 +60,12 @@ public int cardTableShift() { @Override public boolean verifyBarrier() { - return ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED || config.verifyBeforeGC || config.verifyAfterGC; + return ReplacementsUtil.REPLACEMENTS_ASSERTIONS_ENABLED || HotSpotReplacementsUtil.verifyBeforeOrAfterGC(INJECTED_VMCONFIG); } @Override protected byte dirtyCardValue() { - return config.dirtyCardValue; + return HotSpotReplacementsUtil.dirtyCardValue(INJECTED_VMCONFIG); } public static class Templates extends AbstractTemplates { @@ -78,11 +75,11 @@ public static class Templates extends AbstractTemplates { private final SerialWriteBarrierLowerer lowerer; - public Templates(OptionValues options, Iterable factories, Group.Factory factory, HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config) { + public Templates(OptionValues options, Iterable factories, Group.Factory factory, HotSpotProviders providers, TargetDescription target) { super(options, factories, providers, providers.getSnippetReflection(), target); this.lowerer = new SerialWriteBarrierLowerer(factory); - HotSpotSerialWriteBarrierSnippets receiver = new HotSpotSerialWriteBarrierSnippets(config); + HotSpotSerialWriteBarrierSnippets receiver = new HotSpotSerialWriteBarrierSnippets(); serialImpreciseWriteBarrier = snippet(SerialWriteBarrierSnippets.class, "serialImpreciseWriteBarrier", null, receiver, GC_CARD_LOCATION); serialPreciseWriteBarrier = snippet(SerialWriteBarrierSnippets.class, "serialPreciseWriteBarrier", null, receiver, GC_CARD_LOCATION); serialArrayRangeWriteBarrier = snippet(SerialWriteBarrierSnippets.class, "serialArrayRangeWriteBarrier", null, receiver, GC_CARD_LOCATION); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java index 35aab319015..3d39ac9f6aa 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java @@ -31,6 +31,7 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; @@ -49,7 +50,6 @@ import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; /** @@ -57,6 +57,7 @@ * information in {@code klass}. */ @NodeInfo(cycles = CYCLES_1, size = SIZE_1) +@NodeIntrinsicFactory public final class KlassLayoutHelperNode extends FloatingNode implements Canonicalizable, Lowerable { public static final NodeClass TYPE = NodeClass.create(KlassLayoutHelperNode.class); @@ -74,8 +75,7 @@ public static ValueNode create(GraalHotSpotVMConfig config, ValueNode klass, Con return canonical(null, config, klass, stamp, constantReflection, metaAccess); } - @SuppressWarnings("unused") - public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, @InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass) { + public static boolean intrinsify(GraphBuilderContext b, @InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass) { ValueNode valueNode = create(config, klass, b.getConstantReflection(), b.getMetaAccess()); b.push(JavaKind.Int, b.append(valueNode)); return true; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java index 4b2c79c6851..16ec2e1f335 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java @@ -349,6 +349,7 @@ import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PiNode; +import org.graalvm.compiler.nodes.PluginReplacementNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StateSplit; @@ -396,6 +397,7 @@ import org.graalvm.compiler.nodes.extended.MembarNode; import org.graalvm.compiler.nodes.extended.StateSplitProxyNode; import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; @@ -2173,7 +2175,22 @@ boolean check(boolean pluginResult) { } } - @SuppressWarnings("try") + @Override + public void replacePlugin(GeneratedInvocationPlugin plugin, ResolvedJavaMethod targetMethod, ValueNode[] args, PluginReplacementNode.ReplacementFunction replacementFunction) { + assert replacementFunction != null; + JavaType returnType = maybeEagerlyResolve(targetMethod.getSignature().getReturnType(method.getDeclaringClass()), targetMethod.getDeclaringClass()); + StampPair returnStamp = getReplacements().getGraphBuilderPlugins().getOverridingStamp(this, returnType, false); + if (returnStamp == null) { + returnStamp = StampFactory.forDeclaredType(getAssumptions(), returnType, false); + } + ValueNode node = new PluginReplacementNode(returnStamp.getTrustedStamp(), args, replacementFunction, plugin.getClass().getSimpleName()); + if (returnType.getJavaKind() == JavaKind.Void) { + add(node); + } else { + addPush(returnType.getJavaKind(), node); + } + } + protected boolean tryInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) { InvocationPlugin plugin = graphBuilderConfig.getPlugins().getInvocationPlugins().lookupInvocation(targetMethod); if (plugin != null) { @@ -2183,17 +2200,25 @@ protected boolean tryInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, R return false; } - InvocationPluginReceiver pluginReceiver = invocationPluginReceiver.init(targetMethod, args); - assert invokeKind.isDirect() : "Cannot apply invocation plugin on an indirect call site."; + if (applyInvocationPlugin(invokeKind, args, targetMethod, resultType, plugin)) { + return !plugin.isDecorator(); + } + } + return false; + } - InvocationPluginAssertions assertions = Assertions.assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null; - try (DebugCloseable context = openNodeContext(targetMethod)) { - if (plugin.execute(this, targetMethod, pluginReceiver, args)) { - assert assertions.check(true); - return !plugin.isDecorator(); - } else { - assert assertions.check(false); - } + @SuppressWarnings("try") + protected boolean applyInvocationPlugin(InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, InvocationPlugin plugin) { + InvocationPluginReceiver pluginReceiver = invocationPluginReceiver.init(targetMethod, args); + assert invokeKind.isDirect() : "Cannot apply invocation plugin on an indirect call site."; + + InvocationPluginAssertions assertions = Assertions.assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null; + try (DebugCloseable context = openNodeContext(targetMethod)) { + if (plugin.execute(this, targetMethod, pluginReceiver, args)) { + assert assertions.check(true); + return true; + } else { + assert assertions.check(false); } } return false; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_abs.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_abs.java index 0323fe967fb..c6506d70b53 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_abs.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/Math_abs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, 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 @@ -32,12 +32,11 @@ /* */ public class Math_abs extends UnaryMath { - @SuppressWarnings("serial") public static class NaN extends Throwable { } - public static double test(double arg) throws NaN { + public static double testAbsD(double arg) throws NaN { double v = Math.abs(arg); if (Double.isNaN(v)) { // NaN can't be tested against itself @@ -48,43 +47,73 @@ public static double test(double arg) throws NaN { @Test public void run0() throws Throwable { - runTest("test", 5.0d); + runTest("testAbsD", 5.0d); } @Test public void run1() throws Throwable { - runTest("test", -5.0d); + runTest("testAbsD", -5.0d); } @Test public void run2() throws Throwable { - runTest("test", 0.0d); + runTest("testAbsD", 0.0d); } @Test public void run3() throws Throwable { - runTest("test", -0.0d); + runTest("testAbsD", -0.0d); } @Test public void run4() throws Throwable { - runTest("test", java.lang.Double.NEGATIVE_INFINITY); + runTest("testAbsD", java.lang.Double.NEGATIVE_INFINITY); } @Test public void run5() throws Throwable { - runTest("test", java.lang.Double.POSITIVE_INFINITY); + runTest("testAbsD", java.lang.Double.POSITIVE_INFINITY); } @Test public void run6() throws Throwable { - runTest("test", java.lang.Double.NaN); + runTest("testAbsD", java.lang.Double.NaN); } @Test public void run7() { OptionValues options = getInitialOptions(); - ResolvedJavaMethod method = getResolvedJavaMethod("test"); + ResolvedJavaMethod method = getResolvedJavaMethod("testAbsD"); testManyValues(options, method); } + + public static int testAbsI(int arg) { + return Math.abs(arg); + } + + public static long testAbsL(long arg) { + return Math.abs(arg); + } + + @Test + public void run8() { + runTest("testAbsI", Integer.MIN_VALUE); + runTest("testAbsI", -326543323); + runTest("testAbsI", -21325); + runTest("testAbsI", -0); + runTest("testAbsI", 5432); + runTest("testAbsI", 352438548); + runTest("testAbsI", Integer.MAX_VALUE); + } + + @Test + public void run9() { + runTest("testAbsL", Long.MIN_VALUE); + runTest("testAbsL", -425423654342L); + runTest("testAbsL", -21543224L); + runTest("testAbsL", -0L); + runTest("testAbsL", 1325488L); + runTest("testAbsL", 313567897765L); + runTest("testAbsL", Long.MAX_VALUE); + } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitFieldOp.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitFieldOp.java index ef28a69911c..c6f3e887dab 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitFieldOp.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitFieldOp.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2019, Arm Limited and affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Arm Limited and affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,8 @@ */ public class AArch64BitFieldOp extends AArch64LIRInstruction { public enum BitFieldOpCode { + SBFX, + SBFIZ, UBFX, UBFIZ, } @@ -68,8 +70,14 @@ public AArch64BitFieldOp(AArch64BitFieldOp.BitFieldOpCode opcode, AllocatableVal protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register dst = asRegister(result); Register src = asRegister(input); - final int size = input.getPlatformKind().getSizeInBytes() * Byte.SIZE; + final int size = result.getPlatformKind().getSizeInBytes() * Byte.SIZE; switch (opcode) { + case SBFX: + masm.sbfm(size, dst, src, lsb, lsb + width - 1); + break; + case SBFIZ: + masm.sbfm(size, dst, src, size - lsb, width - 1); + break; case UBFX: masm.ubfm(size, dst, src, lsb, lsb + width - 1); break; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java index ab8aa171134..c0de96eb3d9 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorShuffle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java index fef4059219b..1b5abe0df52 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanWalker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -673,9 +673,20 @@ void splitWhenPartialRegisterAvailable(Interval interval, int registerAvailableU splitBeforeUsage(interval, minSplitPos, registerAvailableUntil); } - void splitAndSpillInterval(Interval interval) { + /** + * Split and spill the given interval. The interval is unconditionally split into a left and + * right part. However, if the {@code mustHaveRegUsePos} of the supplied (selected in the + * caller) register is later than the entire range of the left interval after splitting, we can + * allocate the interval to register {@code reg} without spilling it eagerly. + * + * @param interval the {@linkplain Interval} to split and spill + * @param reg a register selected in the caller most suitable for allocating {@code interval} + * to, only used if the left interval after splitting can be allocated to reg since + * the first {@code mustHaveRegUsePos} of {@code reg} is later + * @param mustHaveRegUsePos the first must have usage of the register + */ + void splitAndSpillInterval(Interval interval, Register reg, int mustHaveRegUsePos) { assert interval.state == State.Active || interval.state == State.Inactive : "other states not allowed"; - int currentPos = currentPosition; if (interval.state == State.Inactive) { // the interval is currently inactive, so no spill slot is needed for now. @@ -695,7 +706,40 @@ void splitAndSpillInterval(Interval interval) { splitBeforeUsage(interval, minSplitPos, maxSplitPos); assert interval.nextUsage(RegisterPriority.MustHaveRegister, currentPos) == Integer.MAX_VALUE : "the remaining part is spilled to stack and therefore has no register"; - splitForSpilling(interval); + + if (interval.to() >= mustHaveRegUsePos) { + splitForSpilling(interval); + } else { + /* + * Only need to split'n'spill if the register selected has a usage in the current + * interval's range. + * + * Special case loop phi inputs: if we have a loop phi that has no usage inside the + * loop (and the phi has a usage far away in range) we are tempted to spill the left + * interval at definition of the loop phi, however this can cause move resolution to + * insert spill moves to the stack (phi resolve) inside the body of the loop for + * loop end phi inputs. + * + * In this special scenario we have an interval (loop phi forward end input) that + * has no usage inside the loop just far away from the loop, but the register we + * selected has its first usage outside of the range, so instead of eagerly spilling + * here we use the register and hope it suffices to keep the loop phi in register + * altogether, if not possible we can still spill the register and re-use it + * (hopefully at a better position). + */ + assert reg != null; + boolean needSplit = blockPos[reg.number] <= interval.to(); + int splitPos = blockPos[reg.number]; + assert splitPos > 0 : "invalid splitPos"; + assert needSplit || splitPos > interval.from() : "splitting interval at from"; + interval.assignLocation(reg.asValue(interval.kind())); + if (needSplit) { + // register not available for full interval : so split it + splitWhenPartialRegisterAvailable(interval, splitPos); + } + // perform splitting and spilling for all affected intervals + splitAndSpillIntersectingIntervals(reg); + } } } @@ -789,11 +833,10 @@ boolean allocFreeRegister(Interval interval) { void splitAndSpillIntersectingIntervals(Register reg) { assert reg != null : "no register assigned"; - for (int i = 0; i < spillIntervals[reg.number].size(); i++) { Interval interval = spillIntervals[reg.number].get(i); removeFromList(interval); - splitAndSpillInterval(interval); + splitAndSpillInterval(interval, null, -1/* unconditionally split and spill */); } } @@ -872,8 +915,12 @@ void allocLockedRegister(Interval interval) { throw new OutOfRegistersException("LinearScan: no register found", description); } - splitAndSpillInterval(interval); + splitAndSpillInterval(interval, reg, regUsePos); return; + } else { + if (debug.isLogEnabled()) { + debug.log("not able to spill current interval. firstUsage(register): %d, usePos: %d", firstUsage, regUsePos); + } } break; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java index 2cd5e238353..5ccd14c21e1 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java @@ -189,6 +189,12 @@ public final boolean mustReplaceWithUncompressedNullRegister(JavaConstant nullCo return !uncompressedNullRegister.equals(Register.None) && JavaConstant.NULL_POINTER.equals(nullConstant); } + /** + * This flag indicates whether the assembler should emit a separate deoptimization handler for + * method handle invocations. + */ + private boolean needsMHDeoptHandler = false; + public CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, @@ -729,4 +735,12 @@ public CallContext openCallContext(boolean direct) { } return currentCallContext; } + + public void setNeedsMHDeoptHandler() { + this.needsMHDeoptHandler = true; + } + + public boolean needsMHDeoptHandler() { + return needsMHDeoptHandler; + } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java index b54d77fefe1..532da65772b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/ConvertDeoptimizeToGuardPhase.java @@ -64,7 +64,6 @@ import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.LazyValue; -import org.graalvm.compiler.phases.util.Providers; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.DeoptimizationAction; @@ -83,8 +82,6 @@ */ public class ConvertDeoptimizeToGuardPhase extends BasePhase { - private static final Providers EMPTY_PROVIDERS = new Providers(null, null, null, null, null, null, null, null, null, null); - @Override @SuppressWarnings("try") protected void run(final StructuredGraph graph, CoreProviders context) { @@ -228,7 +225,8 @@ private static void propagateFixed(FixedNode from, StaticDeoptimizingNode deopt, FixedNode next = pred.next(); pred.setNext(guard); guard.setNext(next); - SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(providers != null ? providers : EMPTY_PROVIDERS, false, graph.getAssumptions(), graph.getOptions()); + assert providers != null; + SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(providers, false, graph.getAssumptions(), graph.getOptions()); survivingSuccessor.simplify(simplifierTool); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java index 3fdbe593b80..204bc55a3d5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java @@ -732,12 +732,12 @@ private boolean checkForUnsignedCompare(SimplifierTool tool) { * Check it these two blocks end up at the same place. Meeting at the same merge, or * deoptimizing in the same way. */ - private static boolean sameDestination(AbstractBeginNode succ1, AbstractBeginNode succ2) { + public static boolean sameDestination(AbstractBeginNode succ1, AbstractBeginNode succ2) { Node next1 = succ1.next(); Node next2 = succ2.next(); - if (next1 instanceof EndNode && next2 instanceof EndNode) { - EndNode end1 = (EndNode) next1; - EndNode end2 = (EndNode) next2; + if (next1 instanceof AbstractEndNode && next2 instanceof AbstractEndNode) { + AbstractEndNode end1 = (AbstractEndNode) next1; + AbstractEndNode end2 = (AbstractEndNode) next2; if (end1.merge() == end2.merge()) { for (PhiNode phi : end1.merge().phis()) { if (phi.valueAt(end1) != phi.valueAt(end2)) { @@ -1052,17 +1052,25 @@ private List getNodesForBlock(AbstractBeginNode successor) { */ private boolean isSafeConditionalInput(ValueNode value, AbstractBeginNode successor) { assert successor.hasNoUsages(); - if (value.isConstant() || value instanceof ParameterNode || condition.inputs().contains(value)) { - // Assume constants are cheap to evaluate and Parameters are always evaluated. Any input - // to the condition itself is also unconditionally evaluated. + if (value.isConstant() || condition.inputs().contains(value)) { + // Assume constants are cheap to evaluate. Any input to the condition itself is also + // unconditionally evaluated. return true; } - if (value instanceof FixedNode && graph().isAfterFixedReadPhase()) { - List nodes = getNodesForBlock(successor); - // The successor block is empty so assume that this input evaluated before the - // condition. - return nodes != null && nodes.size() == 2; + if (graph().isAfterFixedReadPhase()) { + if (value instanceof ParameterNode) { + // Assume Parameters are always evaluated but only apply this logic to graphs after + // inlining. Checking for ParameterNode causes it to apply to graphs which are going + // to be inlined into other graphs which is incorrect. + return true; + } + if (value instanceof FixedNode) { + List nodes = getNodesForBlock(successor); + // The successor block is empty so assume that this input evaluated before the + // condition. + return nodes != null && nodes.size() == 2; + } } return false; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java index 22d42cd5ce8..512c26da7bd 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PiNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; import org.graalvm.compiler.graph.spi.CanonicalizerTool; @@ -50,7 +51,6 @@ import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; //JaCoCo Exclude @@ -64,6 +64,7 @@ * also the scheduling restriction enforced by the guard, will go away. */ @NodeInfo(cycles = CYCLES_0, size = SIZE_0) +@NodeIntrinsicFactory public class PiNode extends FloatingGuardedNode implements LIRLowerable, Virtualizable, Canonicalizable, ValueProxy { public static final NodeClass TYPE = NodeClass.create(PiNode.class); @@ -124,8 +125,7 @@ public static ValueNode create(ValueNode object, ValueNode guard) { return new PiNode(object, stamp, guard); } - @SuppressWarnings("unused") - public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode object, ValueNode guard) { + public static boolean intrinsify(GraphBuilderContext b, ValueNode object, ValueNode guard) { Stamp stamp = AbstractPointerStamp.pointerNonNull(object.stamp(NodeView.DEFAULT)); ValueNode value = canonical(object, stamp, (GuardingNode) guard, null); if (value == null) { @@ -135,8 +135,7 @@ public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod metho return true; } - @SuppressWarnings("unused") - public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { + public static boolean intrinsify(GraphBuilderContext b, ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { Stamp stamp = StampFactory.object(exactType ? TypeReference.createExactTrusted(toType) : TypeReference.createWithoutAssumptions(toType), nonNull || StampTool.isPointerNonNull(object.stamp(NodeView.DEFAULT))); ValueNode value = canonical(object, stamp, null, null); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementNode.java new file mode 100644 index 00000000000..3e344bfa5d0 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/PluginReplacementNode.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.nodes; + +import java.util.Map; + +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.NodeInputList; +import org.graalvm.compiler.nodeinfo.NodeCycles; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodeinfo.NodeSize; +import org.graalvm.compiler.nodeinfo.Verbosity; +import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; + +@NodeInfo(nameTemplate = "PluginReplacement/{p#pluginName}", cycles = NodeCycles.CYCLES_IGNORED, size = NodeSize.SIZE_IGNORED) +public final class PluginReplacementNode extends FixedWithNextNode { + public static final NodeClass TYPE = NodeClass.create(PluginReplacementNode.class); + + @Input protected NodeInputList args; + private final ReplacementFunction function; + private final String pluginName; + + public PluginReplacementNode(Stamp stamp, ValueNode[] args, ReplacementFunction function, String pluginName) { + super(TYPE, stamp); + this.args = new NodeInputList<>(this, args); + this.function = function; + this.pluginName = pluginName; + } + + public boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection) { + return function.replace(b, injection, stamp, args); + } + + public interface ReplacementFunction { + boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection, Stamp stamp, NodeInputList args); + } + + @Override + public String toString(Verbosity verbosity) { + if (verbosity == Verbosity.Short) { + return super.toString(verbosity) + "/" + pluginName; + } + return super.toString(verbosity); + } + + @Override + public Map getDebugProperties(Map map) { + map.put("name", pluginName); + return super.getDebugProperties(map); + } +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java index 53791ed9215..b9a662344b6 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, 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 @@ -442,6 +442,7 @@ private void identifyBlock(Block block) { assert nodeToBlock.get(cur) == null; nodeToBlock.set(cur, block); FixedNode next = cur.next(); + assert next != null : cur; if (next instanceof AbstractBeginNode) { block.endNode = cur; return; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java index cbeff5abc6f..9cb2a9b824a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java @@ -64,6 +64,7 @@ public enum BytecodeExceptionKind { OUT_OF_BOUNDS(2, ArrayIndexOutOfBoundsException.class), CLASS_CAST(2, ClassCastException.class), ARRAY_STORE(1, ArrayStoreException.class), + ILLEGAL_ARGUMENT_EXCEPTION(1, IllegalArgumentException.class), DIVISION_BY_ZERO(0, ArithmeticException.class), INTEGER_EXACT_OVERFLOW(0, ArithmeticException.class), LONG_EXACT_OVERFLOW(0, ArithmeticException.class); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java index 718cfa2899d..4fc3d02664c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -47,8 +48,6 @@ import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; /** * Node for a {@linkplain ForeignCallDescriptor foreign} call. @@ -61,6 +60,7 @@ size = SIZE_2, sizeRationale = "Rough estimation of the call operation itself.") // @formatter:on +@NodeIntrinsicFactory public class ForeignCallNode extends AbstractMemoryCheckpoint implements ForeignCall { public static final NodeClass TYPE = NodeClass.create(ForeignCallNode.class); @@ -70,17 +70,17 @@ public class ForeignCallNode extends AbstractMemoryCheckpoint implements Foreign protected final ForeignCallDescriptor descriptor; protected int bci = BytecodeFrame.UNKNOWN_BCI; - public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod targetMethod, @InjectedNodeParameter Stamp returnStamp, @InjectedNodeParameter ForeignCallsProvider foreignCalls, + public static boolean intrinsify(GraphBuilderContext b, @InjectedNodeParameter Stamp returnStamp, @InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallSignature signature, ValueNode... arguments) { ForeignCallDescriptor descriptor = foreignCalls.getDescriptor(signature); - return doIntrinsify(b, targetMethod, returnStamp, descriptor, arguments, false); + return doIntrinsify(b, returnStamp, descriptor, arguments, false); } - public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod targetMethod, @InjectedNodeParameter Stamp returnStamp, ForeignCallDescriptor descriptor, ValueNode... arguments) { - return doIntrinsify(b, targetMethod, returnStamp, descriptor, arguments, false); + public static boolean intrinsify(GraphBuilderContext b, @InjectedNodeParameter Stamp returnStamp, ForeignCallDescriptor descriptor, ValueNode... arguments) { + return doIntrinsify(b, returnStamp, descriptor, arguments, false); } - static boolean doIntrinsify(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Stamp returnStamp, ForeignCallDescriptor descriptor, ValueNode[] arguments, boolean withException) { + static boolean doIntrinsify(GraphBuilderContext b, Stamp returnStamp, ForeignCallDescriptor descriptor, ValueNode[] arguments, boolean withException) { ForeignCall node; if (withException) { node = new ForeignCallWithExceptionNode(descriptor, arguments); @@ -89,8 +89,6 @@ static boolean doIntrinsify(GraphBuilderContext b, ResolvedJavaMethod targetMeth } node.asNode().setStamp(returnStamp); - assert verifyDescriptor(b, targetMethod, descriptor); - /* * Need to update the BCI of a ForeignCallNode so that it gets the stateDuring in the case * that the foreign call can deoptimize. As with all deoptimization, we need a state in a @@ -101,7 +99,7 @@ static boolean doIntrinsify(GraphBuilderContext b, ResolvedJavaMethod targetMeth node.setBci(nonIntrinsicAncestor.bci()); } - JavaKind returnKind = targetMethod.getSignature().getReturnKind(); + JavaKind returnKind = returnStamp.getStackKind(); if (returnKind == JavaKind.Void) { b.add(node.asNode()); } else { @@ -111,17 +109,6 @@ static boolean doIntrinsify(GraphBuilderContext b, ResolvedJavaMethod targetMeth return true; } - static boolean verifyDescriptor(GraphBuilderContext b, ResolvedJavaMethod targetMethod, ForeignCallDescriptor descriptor) { - int parameters = 1; - for (Class arg : descriptor.getArgumentTypes()) { - ResolvedJavaType res = b.getMetaAccess().lookupJavaType(arg); - ResolvedJavaType parameterType = (ResolvedJavaType) targetMethod.getSignature().getParameterType(parameters, targetMethod.getDeclaringClass()); - assert parameterType.equals(res) : descriptor + ": parameter " + parameters + " mismatch: " + res + " != " + parameterType; - parameters++; - } - return true; - } - public ForeignCallNode(ForeignCallsProvider foreignCalls, ForeignCallSignature signature, ValueNode... arguments) { this(TYPE, foreignCalls.getDescriptor(signature), arguments); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallWithExceptionNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallWithExceptionNode.java index 50bef788af4..1b77359cec3 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallWithExceptionNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallWithExceptionNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.graph.spi.Simplifiable; @@ -52,7 +53,6 @@ import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Node for a {@linkplain ForeignCallDescriptor foreign} call with an {@linkplain WithExceptionNode @@ -66,6 +66,7 @@ size = SIZE_2, sizeRationale = "Rough estimation of the call operation itself.") // @formatter:on +@NodeIntrinsicFactory public class ForeignCallWithExceptionNode extends WithExceptionNode implements ForeignCall, Simplifiable { public static final NodeClass TYPE = NodeClass.create(ForeignCallWithExceptionNode.class); @@ -76,8 +77,8 @@ public class ForeignCallWithExceptionNode extends WithExceptionNode implements F protected final ForeignCallDescriptor descriptor; protected int bci = BytecodeFrame.UNKNOWN_BCI; - public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod targetMethod, @InjectedNodeParameter Stamp returnStamp, ForeignCallDescriptor descriptor, ValueNode... arguments) { - return ForeignCallNode.doIntrinsify(b, targetMethod, returnStamp, descriptor, arguments, true); + public static boolean intrinsify(GraphBuilderContext b, @InjectedNodeParameter Stamp returnStamp, ForeignCallDescriptor descriptor, ValueNode... arguments) { + return ForeignCallNode.doIntrinsify(b, returnStamp, descriptor, arguments, true); } public ForeignCallWithExceptionNode(ForeignCallDescriptor descriptor, ValueNode... arguments) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeCopyNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeCopyNode.java index 9a5bac87dae..2eda0a5b544 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeCopyNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeCopyNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, 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 @@ -26,20 +26,21 @@ import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; +import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Copy a value at a location specified as an offset relative to a source object to another location * specified as an offset relative to destination object. No null checks are performed. */ +@NodeIntrinsicFactory public final class UnsafeCopyNode { - public static boolean intrinsify(GraphBuilderContext b, @SuppressWarnings("unused") ResolvedJavaMethod targetMethod, ValueNode sourceObject, ValueNode sourceOffset, ValueNode destinationObject, + public static boolean intrinsify(GraphBuilderContext b, ValueNode sourceObject, ValueNode sourceOffset, ValueNode destinationObject, ValueNode destinationOffset, JavaKind accessKind, LocationIdentity locationIdentity) { RawLoadNode value = b.add(new RawLoadNode(sourceObject, sourceOffset, accessKind, locationIdentity)); b.add(new RawStoreNode(destinationObject, destinationOffset, value, accessKind, locationIdentity)); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedFoldInvocationPlugin.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedFoldInvocationPlugin.java new file mode 100644 index 00000000000..aa1e6a45073 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedFoldInvocationPlugin.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.nodes.graphbuilderconf; + +public abstract class GeneratedFoldInvocationPlugin extends GeneratedInvocationPlugin { + +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java index f0be8ecee97..628a2d0eaa2 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedInvocationPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.NodeIntrinsic; +import org.graalvm.compiler.nodes.PluginReplacementNode; import org.graalvm.compiler.nodes.ValueNode; import jdk.vm.ci.meta.MetaAccessProvider; @@ -80,16 +81,24 @@ protected boolean checkInjectedArgument(GraphBuilderContext b, ValueNode arg, Re return false; } - ResolvedJavaMethod thisExecuteMethod = getExecutedMethod(b); - if (b.getMethod().equals(thisExecuteMethod)) { - // The "execute" method of this plugin is itself being compiled. In (only) this context, - // the injected argument of the call to the @Fold annotated method will be non-null. - if (IS_BUILDING_NATIVE_IMAGE) { + if (IS_BUILDING_NATIVE_IMAGE) { + // The use of this plugin in the plugin itself shouldn't be folded since that defeats + // the purpose of the fold. + ResolvedJavaType foldNodeClass = b.getMetaAccess().lookupJavaType(PluginReplacementNode.ReplacementFunction.class); + if (foldNodeClass.isAssignableFrom(b.getMethod().getDeclaringClass())) { + return false; + } + ResolvedJavaType foldPluginClass = b.getMetaAccess().lookupJavaType(GeneratedFoldInvocationPlugin.class); + if (foldPluginClass.isAssignableFrom(b.getMethod().getDeclaringClass())) { return false; } + } + + ResolvedJavaMethod thisExecuteMethod = getExecutedMethod(b); + if (b.getMethod().equals(thisExecuteMethod)) { return true; } - throw new AssertionError("must pass null to injected argument of " + foldAnnotatedMethod.format("%H.%n(%p)") + ", not " + arg); + throw new AssertionError("must pass null to injected argument of " + foldAnnotatedMethod.format("%H.%n(%p)") + ", not " + arg + " in " + b.getMethod().format("%H.%n(%p)")); } private ResolvedJavaMethod getExecutedMethod(GraphBuilderContext b) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedNodeIntrinsicInvocationPlugin.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedNodeIntrinsicInvocationPlugin.java new file mode 100644 index 00000000000..358592cef66 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedNodeIntrinsicInvocationPlugin.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.nodes.graphbuilderconf; + +import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; + +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; + +public abstract class GeneratedNodeIntrinsicInvocationPlugin extends GeneratedInvocationPlugin { + protected boolean verifyForeignCallDescriptor(GraphBuilderTool b, ResolvedJavaMethod targetMethod, ForeignCallDescriptor descriptor) { + MetaAccessProvider metaAccess = b.getMetaAccess(); + int parameters = 1; + for (Class arg : descriptor.getArgumentTypes()) { + ResolvedJavaType res = metaAccess.lookupJavaType(arg); + ResolvedJavaType parameterType = (ResolvedJavaType) targetMethod.getSignature().getParameterType(parameters, targetMethod.getDeclaringClass()); + assert parameterType.equals(res) : descriptor + ": parameter " + parameters + " mismatch: " + res + " != " + parameterType; + parameters++; + } + return true; + } +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedPluginFactory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedPluginFactory.java new file mode 100644 index 00000000000..363db314a9c --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedPluginFactory.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.nodes.graphbuilderconf; + +public interface GeneratedPluginFactory { + + void registerPlugins(InvocationPlugins plugins, GeneratedPluginInjectionProvider injection); +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodeIntrinsicPluginFactory.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedPluginInjectionProvider.java similarity index 62% rename from src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodeIntrinsicPluginFactory.java rename to src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedPluginInjectionProvider.java index 2abaa077a48..38e2e5686c9 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodeIntrinsicPluginFactory.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GeneratedPluginInjectionProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,21 +26,16 @@ import org.graalvm.compiler.core.common.type.Stamp; -public interface NodeIntrinsicPluginFactory { +public interface GeneratedPluginInjectionProvider { - public interface InjectionProvider { + T getInjectedArgument(Class type); - T getInjectedArgument(Class type); - - /** - * Gets a stamp denoting a given type and non-nullness property. - * - * @param type the type the returned stamp represents - * @param nonNull specifies if the returned stamp denotes a value that is guaranteed to be - * non-null - */ - Stamp getInjectedStamp(Class type, boolean nonNull); - } - - void registerPlugins(InvocationPlugins plugins, InjectionProvider injection); + /** + * Gets a stamp denoting a given type and non-nullness property. + * + * @param type the type the returned stamp represents + * @param nonNull specifies if the returned stamp denotes a value that is guaranteed to be + * non-null + */ + Stamp getInjectedStamp(Class type, boolean nonNull); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java index c7d082548b7..f22a4fe5c2e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java @@ -48,6 +48,7 @@ import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PiNode; +import org.graalvm.compiler.nodes.PluginReplacementNode; import org.graalvm.compiler.nodes.StateSplit; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -377,6 +378,17 @@ default boolean needsExplicitException() { default AbstractBeginNode genExplicitExceptionEdge(@SuppressWarnings("ununsed") BytecodeExceptionKind exceptionKind) { return null; } + + /** + * + * @param plugin + * @param targetMethod + * @param args + * @param replacementFunction + */ + default void replacePlugin(GeneratedInvocationPlugin plugin, ResolvedJavaMethod targetMethod, ValueNode[] args, PluginReplacementNode.ReplacementFunction replacementFunction) { + throw GraalError.unimplemented(); + } } class GraphBuilderContextUtil { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderTool.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderTool.java index 32ec789947a..ada502f8862 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderTool.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,4 +87,10 @@ default boolean canDeferPlugin(GeneratedInvocationPlugin plugin) { // By default generated plugins must be completely processed during parsing. return false; } + + @SuppressWarnings("unused") + default boolean shouldDeferPlugin(GeneratedInvocationPlugin plugin) { + // By default generated plugins must be completely processed during parsing. + return false; + } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java index 7e65ef61197..6f2ba95f288 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/DynamicNewArrayNode.java @@ -106,7 +106,7 @@ public Node canonical(CanonicalizerTool tool) { return this; } ResolvedJavaType type = tool.getConstantReflection().asJavaType(elementType.asConstant()); - if (type != null && !throwsIllegalArgumentException(type) && tool.getMetaAccessExtensionProvider().canConstantFoldDynamicAllocation(type)) { + if (type != null && !throwsIllegalArgumentException(type) && tool.getMetaAccessExtensionProvider().canConstantFoldDynamicAllocation(type.getArrayClass())) { return createNewArrayNode(type); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java index 8e637474cc5..310a3d5b553 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/InstanceOfNode.java @@ -34,6 +34,7 @@ import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; +import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -54,7 +55,6 @@ import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaTypeProfile; -import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.TriState; @@ -62,6 +62,7 @@ * The {@code InstanceOfNode} represents an instanceof test. */ @NodeInfo(cycles = CYCLES_8, size = SIZE_8) +@NodeIntrinsicFactory public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtualizable { public static final NodeClass TYPE = NodeClass.create(InstanceOfNode.class); @@ -220,8 +221,7 @@ public ObjectStamp getCheckedStamp() { @NodeIntrinsic public static native boolean doInstanceof(@ConstantNodeParameter ResolvedJavaType type, Object object); - @SuppressWarnings("unused") - static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ResolvedJavaType type, ValueNode object) { + public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaType type, ValueNode object) { InstanceOfNode node = new InstanceOfNode(StampFactory.objectNonNull(TypeReference.create(b.getAssumptions(), type)), object, null, null); node = b.add(node); b.addPush(JavaKind.Int, ConditionalNode.create(node, NodeView.DEFAULT)); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java index fc41dfd84af..36006f4cd94 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, 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 @@ -38,6 +38,7 @@ import org.graalvm.compiler.nodes.BeginNode; import org.graalvm.compiler.nodes.CallTargetNode; import org.graalvm.compiler.nodes.FixedGuardNode; +import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.NodeView; @@ -177,52 +178,64 @@ public void simplify(SimplifierTool tool) { return; } - Assumptions assumptions = graph().getAssumptions(); - /* - * Even though we are not registering an assumption (see comment below), the optimization is - * only valid when speculative optimizations are enabled. - */ - if (invokeKind().isIndirect() && invokeKind().isInterface() && assumptions != null) { - - // check if the type of the receiver can narrow the result - ValueNode receiver = receiver(); - - // try to turn a interface call into a virtual call - ResolvedJavaType declaredReceiverType = targetMethod().getDeclaringClass(); + if (invokeKind.isInterface()) { + MethodCallTargetNode result = tryDevirtualizeInterfaceCall(receiver(), targetMethod, profile, graph().getAssumptions(), contextType, this, invoke().asNode()); + assert result == this; + } + } + public static MethodCallTargetNode tryDevirtualizeInterfaceCall(ValueNode receiver, ResolvedJavaMethod targetMethod, JavaTypeProfile profile, Assumptions assumptions, ResolvedJavaType contextType, + MethodCallTargetNode callTarget, FixedNode insertionPoint) { + if (assumptions == null) { /* - * We need to check the invoke kind to avoid recursive simplification for virtual - * interface methods calls. + * Even though we are not registering an assumption (see comment below), the + * optimization is only valid when speculative optimizations are enabled. */ - if (declaredReceiverType.isInterface()) { - ResolvedJavaType singleImplementor = declaredReceiverType.getSingleImplementor(); - if (singleImplementor != null && !singleImplementor.equals(declaredReceiverType)) { - TypeReference speculatedType = TypeReference.createTrusted(assumptions, singleImplementor); - if (tryCheckCastSingleImplementor(receiver, speculatedType)) { - return; - } + return callTarget; + } + + // try to turn a interface call into a virtual call + ResolvedJavaType declaredReceiverType = targetMethod.getDeclaringClass(); + + /* + * We need to check the invoke kind to avoid recursive simplification for virtual interface + * methods calls. + */ + if (declaredReceiverType.isInterface()) { + ResolvedJavaType singleImplementor = declaredReceiverType.getSingleImplementor(); + if (singleImplementor != null && !singleImplementor.equals(declaredReceiverType)) { + TypeReference speculatedType = TypeReference.createTrusted(assumptions, singleImplementor); + MethodCallTargetNode callTargetResult = tryCheckCastSingleImplementor(receiver, targetMethod, profile, contextType, speculatedType, insertionPoint, callTarget); + if (callTargetResult != null) { + return callTargetResult; } } + } - if (receiver instanceof UncheckedInterfaceProvider) { - UncheckedInterfaceProvider uncheckedInterfaceProvider = (UncheckedInterfaceProvider) receiver; - Stamp uncheckedStamp = uncheckedInterfaceProvider.uncheckedStamp(); - if (uncheckedStamp != null) { - TypeReference speculatedType = StampTool.typeReferenceOrNull(uncheckedStamp); - if (speculatedType != null) { - tryCheckCastSingleImplementor(receiver, speculatedType); + if (receiver instanceof UncheckedInterfaceProvider) { + UncheckedInterfaceProvider uncheckedInterfaceProvider = (UncheckedInterfaceProvider) receiver; + Stamp uncheckedStamp = uncheckedInterfaceProvider.uncheckedStamp(); + if (uncheckedStamp != null) { + TypeReference speculatedType = StampTool.typeReferenceOrNull(uncheckedStamp); + if (speculatedType != null) { + MethodCallTargetNode callTargetResult = tryCheckCastSingleImplementor(receiver, targetMethod, profile, contextType, speculatedType, insertionPoint, callTarget); + if (callTargetResult != null) { + return callTargetResult; } } } } + return callTarget; } - private boolean tryCheckCastSingleImplementor(ValueNode receiver, TypeReference speculatedType) { + private static MethodCallTargetNode tryCheckCastSingleImplementor(ValueNode receiver, ResolvedJavaMethod targetMethod, JavaTypeProfile profile, ResolvedJavaType contextType, + TypeReference speculatedType, + FixedNode insertionPoint, MethodCallTargetNode callTarget) { ResolvedJavaType singleImplementor = speculatedType.getType(); if (singleImplementor != null) { - ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveConcreteMethod(targetMethod(), invoke().getContextType()); + ResolvedJavaMethod singleImplementorMethod = singleImplementor.resolveConcreteMethod(targetMethod, contextType); if (singleImplementorMethod != null) { - /** + /* * We have an invoke on an interface with a single implementor. We can replace this * with an invoke virtual. * @@ -233,22 +246,32 @@ private boolean tryCheckCastSingleImplementor(ValueNode receiver, TypeReference * an assumption but as we need an instanceof check anyway we can verify both * properties by checking of the receiver is an instance of the single implementor. */ - AnchoringNode anchor = BeginNode.prevBegin(invoke().asNode()); - LogicNode condition = graph().addOrUniqueWithInputs(InstanceOfNode.create(speculatedType, receiver, getProfile(), anchor)); - FixedGuardNode guard = graph().add(new FixedGuardNode(condition, DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, false)); - graph().addBeforeFixed(invoke().asNode(), guard); - ValueNode valueNode = graph().addOrUnique(new PiNode(receiver, StampFactory.objectNonNull(speculatedType), guard)); - arguments().set(0, valueNode); + StructuredGraph graph = insertionPoint.graph(); + AnchoringNode anchor = BeginNode.prevBegin(insertionPoint); + LogicNode condition = graph.addOrUniqueWithInputs(InstanceOfNode.create(speculatedType, receiver, profile, anchor)); + FixedGuardNode guard = graph.add(new FixedGuardNode(condition, DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, false)); + graph.addBeforeFixed(insertionPoint, guard); + InvokeKind invokeKind; if (speculatedType.isExact()) { - setInvokeKind(InvokeKind.Special); + invokeKind = InvokeKind.Special; + } else { + invokeKind = InvokeKind.Virtual; + } + MethodCallTargetNode callTargetResult = callTarget; + ValueNode valueNode = graph.addOrUnique(new PiNode(receiver, StampFactory.objectNonNull(speculatedType), guard)); + if (callTarget.isAlive()) { + callTarget.arguments().set(0, valueNode); + callTargetResult.setInvokeKind(invokeKind); + callTargetResult.setTargetMethod(singleImplementorMethod); } else { - setInvokeKind(InvokeKind.Virtual); + ValueNode[] arguments = callTarget.arguments().toArray(new ValueNode[callTarget.arguments().size()]); + arguments[0] = valueNode; + callTargetResult = new MethodCallTargetNode(invokeKind, singleImplementorMethod, arguments, callTarget.returnStamp, profile); } - setTargetMethod(singleImplementorMethod); - return true; + return callTargetResult; } } - return false; + return null; } public JavaTypeProfile getProfile() { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/CoreProvidersImpl.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/CoreProvidersImpl.java index db64973c463..002cb0b114c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/CoreProvidersImpl.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/CoreProvidersImpl.java @@ -100,4 +100,20 @@ public PlatformConfigurationProvider getPlatformConfigurationProvider() { public MetaAccessExtensionProvider getMetaAccessExtensionProvider() { return metaAccessExtensionProvider; } + + public CoreProvidersImpl copyWith(ConstantReflectionProvider substitution) { + assert this.getClass() == CoreProvidersImpl.class : "must override in " + getClass(); + return new CoreProvidersImpl(metaAccess, substitution, constantFieldProvider, lowerer, replacements, stampProvider, foreignCalls, platformConfigurationProvider, metaAccessExtensionProvider); + } + + public CoreProvidersImpl copyWith(ConstantFieldProvider substitution) { + assert this.getClass() == CoreProvidersImpl.class : "must override in " + getClass(); + return new CoreProvidersImpl(metaAccess, constantReflection, substitution, lowerer, replacements, stampProvider, foreignCalls, platformConfigurationProvider, metaAccessExtensionProvider); + } + + public CoreProvidersImpl copyWith(Replacements substitution) { + assert this.getClass() == CoreProvidersImpl.class : "must override in " + getClass(); + return new CoreProvidersImpl(metaAccess, constantReflection, constantFieldProvider, lowerer, substitution, stampProvider, foreignCalls, platformConfigurationProvider, + metaAccessExtensionProvider); + } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java index 13f2bb22356..6a1b31b3f8a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/DelegatingReplacements.java @@ -27,6 +27,7 @@ import org.graalvm.compiler.api.replacements.SnippetTemplateCache; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.nodes.Cancellable; @@ -56,6 +57,16 @@ public CoreProviders getProviders() { return delegate.getProviders(); } + @Override + public T getInjectedArgument(Class type) { + return delegate.getInjectedArgument(type); + } + + @Override + public Stamp getInjectedStamp(Class type, boolean nonNull) { + return delegate.getInjectedStamp(type, nonNull); + } + @Override public GraphBuilderConfiguration.Plugins getGraphBuilderPlugins() { return delegate.getGraphBuilderPlugins(); @@ -82,6 +93,11 @@ public boolean isSnippet(ResolvedJavaMethod method) { return delegate.isSnippet(method); } + @Override + public boolean isEncodingSnippets() { + return delegate.isEncodingSnippets(); + } + @Override public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) { delegate.registerSnippet(method, original, receiver, trackNodeSourcePosition, options); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java index d59fa4f026b..1dd90651097 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/Replacements.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.nodes.Cancellable; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; @@ -45,7 +46,7 @@ /** * Interface for managing replacements. */ -public interface Replacements { +public interface Replacements extends GeneratedPluginInjectionProvider { CoreProviders getProviders(); @@ -84,6 +85,14 @@ StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursi */ boolean isSnippet(ResolvedJavaMethod method); + /** + * Returns {@code true} if this {@code Replacements} is being used for preparation of snippets + * and substitutions for libgraal. + */ + default boolean isEncodingSnippets() { + return false; + } + /** * Registers a method as snippet. */ diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java index 74d80f46c8c..5eca1211aec 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java @@ -41,6 +41,7 @@ import org.graalvm.compiler.code.SourceStackTraceBailoutException; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeBitMap; @@ -55,6 +56,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ControlSinkNode; import org.graalvm.compiler.nodes.ControlSplitNode; +import org.graalvm.compiler.nodes.EndNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.FrameState; @@ -63,6 +65,7 @@ import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.LoopEndNode; import org.graalvm.compiler.nodes.LoopExitNode; +import org.graalvm.compiler.nodes.MergeNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.PiNode; @@ -73,9 +76,11 @@ import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.ValueProxyNode; import org.graalvm.compiler.nodes.WithExceptionNode; +import org.graalvm.compiler.nodes.extended.MultiGuardNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.java.MonitorIdNode; +import org.graalvm.compiler.nodes.memory.MemoryPhiNode; import org.graalvm.compiler.nodes.spi.ArrayLengthProvider; import org.graalvm.compiler.nodes.spi.ArrayLengthProvider.FindLengthMode; import org.graalvm.compiler.nodes.spi.CoreProviders; @@ -124,7 +129,7 @@ private static void killCFGInner(FixedNode node) { debug.dump(DebugContext.DETAILED_LEVEL, node.graph(), "After fixing merges (killCFG %s)", node); // Mark non-fixed nodes - markUsages(markedNodes); + markUsagesForKill(markedNodes); // Detach marked nodes from non-marked nodes for (Node marked : markedNodes) { @@ -223,19 +228,37 @@ private static void fixSurvivingAffectedMerges(EconomicSet markedNodes, Ec } } - private static void markUsages(EconomicSet markedNodes) { + private static void markUsagesForKill(EconomicSet markedNodes) { NodeStack workStack = new NodeStack(markedNodes.size() + 4); for (Node marked : markedNodes) { workStack.push(marked); } + ArrayList unmarkedMultiGuards = new ArrayList<>(); while (!workStack.isEmpty()) { Node marked = workStack.pop(); for (Node usage : marked.usages()) { - if (!markedNodes.contains(usage)) { + boolean doMark = true; + if (usage instanceof MultiGuardNode) { + // Only mark a MultiGuardNode for deletion if all of its guards are marked for + // deletion. Otherwise, we would kill nodes outside the path to be killed. + MultiGuardNode multiGuard = (MultiGuardNode) usage; + for (Node guard : multiGuard.inputs()) { + if (!markedNodes.contains(guard)) { + doMark = false; + unmarkedMultiGuards.add(multiGuard); + } + } + } + if (doMark && !markedNodes.contains(usage)) { workStack.push(usage); markedNodes.add(usage); } } + // Detach unmarked multi guards from the marked node + for (MultiGuardNode multiGuard : unmarkedMultiGuards) { + multiGuard.replaceFirstInput(marked, null); + } + unmarkedMultiGuards.clear(); } } @@ -1144,4 +1167,74 @@ public static boolean checkFrameState(FixedNode start, int maxDepth) { public static boolean mayRemoveSplit(IfNode ifNode) { return GraphUtil.checkFrameState(ifNode.trueSuccessor(), MAX_FRAMESTATE_SEARCH_DEPTH) && GraphUtil.checkFrameState(ifNode.falseSuccessor(), MAX_FRAMESTATE_SEARCH_DEPTH); } + + /** + * An if node with an empty body at the end of a loop is represented with a {@link LoopEndNode} + * at the end of each path. For some optimizations it is more useful to have a representation of + * the if statement as a proper diamond with a merge after the two bodies, followed by a + * {@link LoopEndNode}. This method tries to transform the given {@code ifNode} into such a + * form, introducing new phi nodes for the diamond and patching up the loop's phis accordingly. + * On success, the newly introduced loop end node is returned. If the given {@code ifNode} is + * not an if statement with empty bodies at the end of the loop, the graph is not modified, and + * {@code null} is returned. + * + * Note that the diamond representation is not canonical and will be undone by the next + * application of {@link LoopEndNode#simplify(SimplifierTool)}. + */ + public static LoopEndNode tryToTransformToEmptyLoopDiamond(IfNode ifNode, LoopBeginNode loopBegin) { + if (ifNode.trueSuccessor().next() instanceof AbstractEndNode && ifNode.falseSuccessor().next() instanceof AbstractEndNode) { + AbstractEndNode trueEnd = (AbstractEndNode) ifNode.trueSuccessor().next(); + AbstractEndNode falseEnd = (AbstractEndNode) ifNode.falseSuccessor().next(); + if (trueEnd.merge() == loopBegin && falseEnd.merge() == loopBegin) { + StructuredGraph graph = loopBegin.graph(); + for (PhiNode phi : loopBegin.phis()) { + if (!(phi instanceof ValuePhiNode || phi instanceof MemoryPhiNode)) { + return null; + } + } + + EndNode newTrueEnd = graph.add(new EndNode()); + EndNode newFalseEnd = graph.add(new EndNode()); + MergeNode merge = graph.add(new MergeNode()); + merge.addForwardEnd(newTrueEnd); + merge.addForwardEnd(newFalseEnd); + + ArrayList replacementPhis = new ArrayList<>(loopBegin.phis().count()); + for (PhiNode phi : loopBegin.phis()) { + if (phi instanceof ValuePhiNode) { + ValuePhiNode valuePhi = (ValuePhiNode) phi; + ValuePhiNode newPhi = phi.graph().unique(new ValuePhiNode(valuePhi.stamp(NodeView.DEFAULT), merge, new ValueNode[]{valuePhi.valueAt(trueEnd), valuePhi.valueAt(falseEnd)})); + replacementPhis.add(newPhi); + } else if (phi instanceof MemoryPhiNode) { + MemoryPhiNode memoryPhi = (MemoryPhiNode) phi; + MemoryPhiNode newPhi = phi.graph().unique(new MemoryPhiNode(merge, memoryPhi.getLocationIdentity(), new ValueNode[]{memoryPhi.valueAt(trueEnd), memoryPhi.valueAt(falseEnd)})); + replacementPhis.add(newPhi); + } else { + GraalError.shouldNotReachHere(); + } + } + + loopBegin.removeEnd(trueEnd); + loopBegin.removeEnd(falseEnd); + ifNode.trueSuccessor().setNext(newTrueEnd); + ifNode.falseSuccessor().setNext(newFalseEnd); + trueEnd.safeDelete(); + falseEnd.safeDelete(); + + LoopEndNode newEnd = graph.add(new LoopEndNode(loopBegin)); + merge.setNext(newEnd); + int i = 0; + for (PhiNode phi : loopBegin.phis()) { + ValueNode replacementPhi = replacementPhis.get(i); + assert (phi instanceof ValuePhiNode && replacementPhi instanceof ValuePhiNode) || (phi instanceof MemoryPhiNode && replacementPhi instanceof MemoryPhiNode); + phi.addInput(replacementPhi); + i++; + } + assert i == replacementPhis.size() : "did not consume all values"; + + return newEnd; + } + } + return null; + } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java index a99097abfe8..3adca83c12f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java @@ -129,7 +129,12 @@ public static void parseOption(String name, Object uncheckedValue, EconomicMap", match.getName()); } } - throw new IllegalArgumentException(msg.toString()); + IllegalArgumentException iae = new IllegalArgumentException(msg.toString()); + if (isFromLibGraal(iae)) { + msg.format("%nIf %s is a libgraal option, it must be specified with '-Dlibgraal.%s' as opposed to '-Dgraal.%s'.", name, name, name); + iae = new IllegalArgumentException(msg.toString()); + } + throw iae; } Object value = parseOptionValue(desc, uncheckedValue); @@ -137,6 +142,15 @@ public static void parseOption(String name, Object uncheckedValue, EconomicMap optionType = desc.getOptionValueType(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java index 6ab652dfb48..1ecc9672348 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.Invoke; +import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.phases.common.inlining.InliningUtil; import org.graalvm.compiler.phases.util.Providers; @@ -48,7 +49,7 @@ public AssumptionInlineInfo(Invoke invoke, ResolvedJavaMethod concrete, Assumpti } @Override - public EconomicSet inline(Providers providers, String reason) { + public EconomicSet inline(CoreProviders providers, String reason) { takenAssumption.recordTo(invoke.asNode().graph().getAssumptions()); return super.inline(providers, reason); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java index 231600da40f..9dbdf5bf68b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import jdk.internal.vm.compiler.collections.EconomicSet; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; +import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable; import org.graalvm.compiler.phases.util.Providers; @@ -53,7 +54,7 @@ public void suppressNullCheck() { } @Override - public EconomicSet inline(Providers providers, String reason) { + public EconomicSet inline(CoreProviders providers, String reason) { return inline(invoke, concrete, inlineableElement, !suppressNullCheck, reason); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java index 4f93cc6c065..6bc4f970a8c 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable; @@ -77,7 +78,7 @@ public interface InlineInfo { * * @return a collection of nodes that need to be canonicalized after the inlining */ - EconomicSet inline(Providers providers, String reason); + EconomicSet inline(CoreProviders providers, String reason); /** * Try to make the call static bindable to avoid interface and virtual method calls. diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java index 9b6a3707d77..bd3328de856 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java @@ -53,6 +53,7 @@ import org.graalvm.compiler.nodes.java.ExceptionObjectNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.java.TypeSwitchNode; +import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.phases.common.inlining.InliningUtil; @@ -158,7 +159,7 @@ public void setInlinableElement(int index, Inlineable inlineableElement) { } @Override - public EconomicSet inline(Providers providers, String reason) { + public EconomicSet inline(CoreProviders providers, String reason) { if (hasSingleMethod()) { return inlineSingleMethod(graph(), providers.getStampProvider(), providers.getConstantReflection(), reason); } else { @@ -184,7 +185,7 @@ private boolean shouldFallbackToInvoke() { return notRecordedTypeProbability > 0; } - private EconomicSet inlineMultipleMethods(StructuredGraph graph, Providers providers, String reason) { + private EconomicSet inlineMultipleMethods(StructuredGraph graph, CoreProviders providers, String reason) { int numberOfMethods = concretes.size(); FixedNode continuation = invoke.next(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java index efea0840f62..e68b0e46c1f 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.CompareNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; +import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.phases.common.inlining.InliningUtil; import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable; import org.graalvm.compiler.phases.util.Providers; @@ -101,7 +102,7 @@ public void setInlinableElement(int index, Inlineable inlineableElement) { } @Override - public EconomicSet inline(Providers providers, String reason) { + public EconomicSet inline(CoreProviders providers, String reason) { createGuard(graph(), providers); return inline(invoke, concrete, inlineableElement, false, reason); } @@ -113,7 +114,7 @@ public void tryToDevirtualizeInvoke(Providers providers) { } @SuppressWarnings("try") - private void createGuard(StructuredGraph graph, Providers providers) { + private void createGuard(StructuredGraph graph, CoreProviders providers) { try (DebugCloseable context = invoke.asNode().withNodeSourcePosition()) { ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke); LoadHubNode receiverHub = graph.unique(new LoadHubNode(providers.getStampProvider(), nonNullReceiver)); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java index 45537e59ab6..2f55d2968a1 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java @@ -68,7 +68,6 @@ import org.graalvm.compiler.phases.common.inlining.info.elem.InlineableGraph; import org.graalvm.compiler.phases.common.inlining.policy.InliningPolicy; import org.graalvm.compiler.phases.tiers.HighTierContext; -import org.graalvm.compiler.phases.util.Providers; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.meta.Assumptions.AssumptionResult; @@ -412,7 +411,7 @@ private void doInline(CallsiteHolderExplorable callerCallsiteHolder, MethodInvoc try (DebugContext.Scope scope = debug.scope("doInline", callerGraph)) { EconomicSet canonicalizedNodes = EconomicSet.create(Equivalence.IDENTITY); canonicalizedNodes.addAll(calleeInfo.invoke().asNode().usages()); - EconomicSet parameterUsages = calleeInfo.inline(new Providers(context), reason); + EconomicSet parameterUsages = calleeInfo.inline(context.getProviders(), reason); canonicalizedNodes.addAll(parameterUsages); counterInliningRuns.increment(debug); debug.dump(DebugContext.DETAILED_LEVEL, callerGraph, "after %s", calleeInfo); @@ -468,7 +467,7 @@ private boolean tryToInline(MethodInvocation calleeInvocation, int inliningDepth } if (context.getOptimisticOptimizations().devirtualizeInvokes(calleeInfo.graph().getOptions())) { - calleeInfo.tryToDevirtualizeInvoke(new Providers(context)); + calleeInfo.tryToDevirtualizeInvoke(context.getProviders()); } return false; @@ -496,7 +495,7 @@ private boolean tryToInline(MethodInvocation calleeInvocation, int inliningDepth *

* The {@link InlineInfo} used to get things rolling is kept around in the * {@link MethodInvocation}, it will be needed in case of inlining, see - * {@link InlineInfo#inline(Providers, String)} + * {@link InlineInfo#inline(org.graalvm.compiler.nodes.spi.CoreProviders, String)} *

*/ private void processNextInvoke() { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/HighTierContext.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/HighTierContext.java index ad90f232196..fff23489597 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/HighTierContext.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/HighTierContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,4 +48,9 @@ public PhaseSuite getGraphBuilderSuite() { public OptimisticOptimizations getOptimisticOptimizations() { return optimisticOpts; } + + @Override + public Providers getProviders() { + return (Providers) super.getProviders(); + } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java index cdd9a46cd98..1c789aecceb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/Providers.java @@ -24,16 +24,17 @@ package org.graalvm.compiler.phases.util; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.spi.CodeGenProviders; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.spi.MetaAccessExtensionProvider; -import org.graalvm.compiler.nodes.spi.CoreProviders; import org.graalvm.compiler.nodes.spi.CoreProvidersImpl; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.PlatformConfigurationProvider; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.spi.StampProvider; +import org.graalvm.compiler.word.WordTypes; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.meta.ConstantReflectionProvider; @@ -46,21 +47,22 @@ public class Providers extends CoreProvidersImpl implements CodeGenProviders { private final CodeCacheProvider codeCache; + private final SnippetReflectionProvider snippetReflection; + private final WordTypes wordTypes; + public Providers(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, ForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, PlatformConfigurationProvider platformConfigurationProvider, - MetaAccessExtensionProvider metaAccessExtensionProvider) { + MetaAccessExtensionProvider metaAccessExtensionProvider, SnippetReflectionProvider snippetReflection, WordTypes wordTypes) { super(metaAccess, constantReflection, constantFieldProvider, lowerer, replacements, stampProvider, foreignCalls, platformConfigurationProvider, metaAccessExtensionProvider); this.codeCache = codeCache; + this.snippetReflection = snippetReflection; + this.wordTypes = wordTypes; } public Providers(Providers copyFrom) { this(copyFrom.getMetaAccess(), copyFrom.getCodeCache(), copyFrom.getConstantReflection(), copyFrom.getConstantFieldProvider(), copyFrom.getForeignCalls(), copyFrom.getLowerer(), - copyFrom.getReplacements(), copyFrom.getStampProvider(), copyFrom.getPlatformConfigurationProvider(), copyFrom.getMetaAccessExtensionProvider()); - } - - public Providers(CoreProviders copyFrom) { - this(copyFrom.getMetaAccess(), null, copyFrom.getConstantReflection(), copyFrom.getConstantFieldProvider(), null, copyFrom.getLowerer(), copyFrom.getReplacements(), - copyFrom.getStampProvider(), copyFrom.getPlatformConfigurationProvider(), copyFrom.getMetaAccessExtensionProvider()); + copyFrom.getReplacements(), copyFrom.getStampProvider(), copyFrom.getPlatformConfigurationProvider(), copyFrom.getMetaAccessExtensionProvider(), + copyFrom.getSnippetReflection(), copyFrom.getWordTypes()); } @Override @@ -68,20 +70,38 @@ public CodeCacheProvider getCodeCache() { return codeCache; } + public SnippetReflectionProvider getSnippetReflection() { + return snippetReflection; + } + + public WordTypes getWordTypes() { + return wordTypes; + } + + @Override public Providers copyWith(ConstantReflectionProvider substitution) { - assert this.getClass() == Providers.class : "must override in " + getClass(); - return new Providers(metaAccess, codeCache, substitution, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, - metaAccessExtensionProvider); + assert this.getClass() == Providers.class : "must override"; + return new Providers(metaAccess, codeCache, substitution, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, + snippetReflection, wordTypes); } + @Override public Providers copyWith(ConstantFieldProvider substitution) { - assert this.getClass() == Providers.class : "must override in " + getClass(); - return new Providers(metaAccess, codeCache, constantReflection, substitution, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider); + assert this.getClass() == Providers.class : "must override"; + return new Providers(metaAccess, codeCache, constantReflection, substitution, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, + snippetReflection, wordTypes); } + @Override public Providers copyWith(Replacements substitution) { assert this.getClass() == Providers.class : "must override in " + getClass(); return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, substitution, stampProvider, platformConfigurationProvider, - metaAccessExtensionProvider); + metaAccessExtensionProvider, snippetReflection, wordTypes); + } + + public Providers copyWith(MetaAccessExtensionProvider substitution) { + assert this.getClass() == Providers.class : getClass() + " must override"; + return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, substitution, + snippetReflection, wordTypes); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java index 294d64be5df..31a43a29533 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java @@ -34,6 +34,8 @@ import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool.RoundingMode; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.AbsNode; +import org.graalvm.compiler.nodes.calc.IntegerMulHighNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; @@ -147,6 +149,17 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec if (useFMAIntrinsics && JavaVersionUtil.JAVA_SPEC > 8) { registerFMA(r); } + registerIntegerAbs(r); + + if (JavaVersionUtil.JAVA_SPEC >= 10) { + r.register2("multiplyHigh", Long.TYPE, Long.TYPE, new InvocationPlugin() { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) { + b.push(JavaKind.Long, b.append(new IntegerMulHighNode(x, y))); + return true; + } + }); + } } private static void registerFMA(Registration r) { @@ -176,6 +189,25 @@ public boolean apply(GraphBuilderContext b, }); } + private static void registerIntegerAbs(Registration r) { + r.register1("abs", Integer.TYPE, new InvocationPlugin() { + + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { + b.push(JavaKind.Int, b.append(new AbsNode(value).canonical(null))); + return true; + } + }); + r.register1("abs", Long.TYPE, new InvocationPlugin() { + + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { + b.push(JavaKind.Long, b.append(new AbsNode(value).canonical(null))); + return true; + } + }); + } + private static void registerUnaryMath(Registration r, String name, UnaryOperation operation) { r.register1(name, Double.TYPE, new InvocationPlugin() { @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64LongSubstitutions.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64LongSubstitutions.java index b3802fabe1f..5560aff56cb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64LongSubstitutions.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64LongSubstitutions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,32 +27,18 @@ // JaCoCo Exclude import static org.graalvm.compiler.replacements.NodeIntrinsificationProvider.INJECTED_TARGET; +import static org.graalvm.compiler.replacements.amd64.AMD64IntegerSubstitutions.lzcnt; +import static org.graalvm.compiler.replacements.amd64.AMD64IntegerSubstitutions.tzcnt; import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.replacements.nodes.BitScanForwardNode; import org.graalvm.compiler.replacements.nodes.BitScanReverseNode; -import jdk.vm.ci.amd64.AMD64; -import jdk.vm.ci.code.TargetDescription; - @ClassSubstitution(Long.class) public class AMD64LongSubstitutions { - @Fold - static boolean lzcnt(@Fold.InjectedParameter TargetDescription target) { - AMD64 arch = (AMD64) target.arch; - return arch.getFeatures().contains(AMD64.CPUFeature.LZCNT) && arch.getFlags().contains(AMD64.Flag.UseCountLeadingZerosInstruction); - } - - @Fold - static boolean tzcnt(@Fold.InjectedParameter TargetDescription target) { - AMD64 arch = (AMD64) target.arch; - return arch.getFeatures().contains(AMD64.CPUFeature.BMI1) && arch.getFlags().contains(AMD64.Flag.UseCountTrailingZerosInstruction); - } - @MethodSubstitution @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_NONVIRTUAL", justification = "foldable method parameters are injected") public static int numberOfLeadingZeros(long i) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringLatin1Substitutions.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringLatin1Substitutions.java index 13ff6fdd23b..138593a93c5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringLatin1Substitutions.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringLatin1Substitutions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,9 +28,12 @@ import static org.graalvm.compiler.api.directives.GraalDirectives.UNLIKELY_PROBABILITY; import static org.graalvm.compiler.api.directives.GraalDirectives.SLOWPATH_PROBABILITY; import static org.graalvm.compiler.api.directives.GraalDirectives.injectBranchProbability; +import static org.graalvm.compiler.replacements.ReplacementsUtil.byteArrayBaseOffset; +import static org.graalvm.compiler.replacements.ReplacementsUtil.byteArrayIndexScale; +import static org.graalvm.compiler.replacements.ReplacementsUtil.charArrayBaseOffset; +import static org.graalvm.compiler.replacements.ReplacementsUtil.charArrayIndexScale; import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.nodes.DeoptimizeNode; @@ -54,26 +57,6 @@ @ClassSubstitution(className = "java.lang.StringLatin1", optional = true) public class AMD64StringLatin1Substitutions { - @Fold - static int byteArrayBaseOffset(@InjectedParameter MetaAccessProvider metaAccess) { - return metaAccess.getArrayBaseOffset(JavaKind.Byte); - } - - @Fold - static int byteArrayIndexScale(@InjectedParameter MetaAccessProvider metaAccess) { - return metaAccess.getArrayIndexScale(JavaKind.Byte); - } - - @Fold - static int charArrayBaseOffset(@InjectedParameter MetaAccessProvider metaAccess) { - return metaAccess.getArrayBaseOffset(JavaKind.Char); - } - - @Fold - static int charArrayIndexScale(@InjectedParameter MetaAccessProvider metaAccess) { - return metaAccess.getArrayIndexScale(JavaKind.Char); - } - /** Marker value for the {@link InjectedParameter} injected parameter. */ static final MetaAccessProvider INJECTED = null; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java index b11803aa762..7163d7a1aad 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,9 +27,10 @@ import static org.graalvm.compiler.api.directives.GraalDirectives.LIKELY_PROBABILITY; import static org.graalvm.compiler.api.directives.GraalDirectives.UNLIKELY_PROBABILITY; import static org.graalvm.compiler.api.directives.GraalDirectives.injectBranchProbability; +import static org.graalvm.compiler.replacements.ReplacementsUtil.charArrayBaseOffset; +import static org.graalvm.compiler.replacements.ReplacementsUtil.charArrayIndexScale; import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.core.common.SuppressFBWarnings; @@ -51,16 +52,6 @@ @ClassSubstitution(String.class) public class AMD64StringSubstitutions { - @Fold - static int charArrayBaseOffset(@InjectedParameter MetaAccessProvider metaAccess) { - return metaAccess.getArrayBaseOffset(JavaKind.Char); - } - - @Fold - static int charArrayIndexScale(@InjectedParameter MetaAccessProvider metaAccess) { - return metaAccess.getArrayIndexScale(JavaKind.Char); - } - /** Marker value for the {@link InjectedParameter} injected parameter. */ static final MetaAccessProvider INJECTED = null; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16Substitutions.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16Substitutions.java index 2644444183b..b761cd9e2b7 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16Substitutions.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringUTF16Substitutions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,18 +24,16 @@ package org.graalvm.compiler.replacements.amd64; -import jdk.vm.ci.meta.DeoptimizationAction; -import jdk.vm.ci.meta.DeoptimizationReason; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.MetaAccessProvider; - import static org.graalvm.compiler.api.directives.GraalDirectives.LIKELY_PROBABILITY; -import static org.graalvm.compiler.api.directives.GraalDirectives.UNLIKELY_PROBABILITY; import static org.graalvm.compiler.api.directives.GraalDirectives.SLOWPATH_PROBABILITY; +import static org.graalvm.compiler.api.directives.GraalDirectives.UNLIKELY_PROBABILITY; import static org.graalvm.compiler.api.directives.GraalDirectives.injectBranchProbability; +import static org.graalvm.compiler.replacements.ReplacementsUtil.byteArrayBaseOffset; +import static org.graalvm.compiler.replacements.ReplacementsUtil.byteArrayIndexScale; +import static org.graalvm.compiler.replacements.ReplacementsUtil.charArrayBaseOffset; +import static org.graalvm.compiler.replacements.ReplacementsUtil.charArrayIndexScale; import org.graalvm.compiler.api.replacements.ClassSubstitution; -import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.nodes.DeoptimizeNode; @@ -46,6 +44,11 @@ import org.graalvm.compiler.word.Word; import jdk.internal.vm.compiler.word.Pointer; +import jdk.vm.ci.meta.DeoptimizationAction; +import jdk.vm.ci.meta.DeoptimizationReason; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MetaAccessProvider; + // JaCoCo Exclude /** @@ -55,27 +58,6 @@ */ @ClassSubstitution(className = "java.lang.StringUTF16", optional = true) public class AMD64StringUTF16Substitutions { - - @Fold - static int byteArrayBaseOffset(@InjectedParameter MetaAccessProvider metaAccess) { - return metaAccess.getArrayBaseOffset(JavaKind.Byte); - } - - @Fold - static int byteArrayIndexScale(@InjectedParameter MetaAccessProvider metaAccess) { - return metaAccess.getArrayIndexScale(JavaKind.Byte); - } - - @Fold - static int charArrayBaseOffset(@InjectedParameter MetaAccessProvider metaAccess) { - return metaAccess.getArrayBaseOffset(JavaKind.Char); - } - - @Fold - static int charArrayIndexScale(@InjectedParameter MetaAccessProvider metaAccess) { - return metaAccess.getArrayIndexScale(JavaKind.Char); - } - /** * Marker value for the {@link InjectedParameter} injected parameter. */ diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.jdk10.test/src/org/graalvm/compiler/replacements/jdk10/test/MathMultiplyHighTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.jdk10.test/src/org/graalvm/compiler/replacements/jdk10/test/MathMultiplyHighTest.java new file mode 100644 index 00000000000..9e512cac400 --- /dev/null +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.jdk10.test/src/org/graalvm/compiler/replacements/jdk10/test/MathMultiplyHighTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, Arm Limited. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.replacements.jdk10.test; + +import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.nodes.calc.IntegerMulHighNode; +import org.graalvm.compiler.replacements.test.MethodSubstitutionTest; +import org.graalvm.compiler.runtime.RuntimeProvider; +import org.junit.Test; + +import jdk.vm.ci.aarch64.AArch64; +import jdk.vm.ci.code.TargetDescription; + +public class MathMultiplyHighTest extends MethodSubstitutionTest { + private static final long[] INPUT = {Long.MIN_VALUE, Long.MIN_VALUE + 1, 0XF64543679090840EL, -1L, + 0L, 0X5L, 0X100L, 0X4336624L, 0x25842900000L, Long.MAX_VALUE - 1, Long.MAX_VALUE}; + + public static long multiplyHigh(long m, long n) { + return Math.multiplyHigh(m, n); + } + + @Test + public void testMultiplyHigh() { + TargetDescription target = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getTarget(); + if (target.arch instanceof AArch64) { + assertInGraph(testGraph("multiplyHigh"), IntegerMulHighNode.class); + } + for (long input1 : INPUT) { + for (long input2 : INPUT) { + test("multiplyHigh", input1, input2); + } + } + } +} diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java index 42a7c0f4d89..da8d84a717a 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedFoldPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,17 +57,27 @@ protected TypeElement getAnnotationClass(AbstractProcessor processor) { } @Override - public void extraImports(Set imports) { + protected String pluginSuperclass() { + return "GeneratedFoldInvocationPlugin"; + } + + @Override + public void extraImports(AbstractProcessor processor, Set imports) { imports.add("jdk.vm.ci.meta.JavaConstant"); imports.add("jdk.vm.ci.meta.JavaKind"); imports.add("org.graalvm.compiler.nodes.ConstantNode"); + imports.add("org.graalvm.compiler.core.common.type.Stamp"); } @Override - protected InjectedDependencies createExecute(AbstractProcessor processor, PrintWriter out) { - InjectedDependencies deps = new InjectedDependencies(); + protected void createExecute(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps) { List params = intrinsicMethod.getParameters(); + out.printf(" if (b.shouldDeferPlugin(this)) {\n"); + out.printf(" b.replacePlugin(this, targetMethod, args, %s.FUNCTION);\n", getReplacementName()); + out.printf(" return true;\n"); + out.printf(" }\n"); + int argCount = 0; Object receiver; if (intrinsicMethod.getModifiers().contains(Modifier.STATIC)) { @@ -75,18 +85,18 @@ protected InjectedDependencies createExecute(AbstractProcessor processor, PrintW } else { receiver = "arg0"; TypeElement type = (TypeElement) intrinsicMethod.getEnclosingElement(); - constantArgument(processor, out, deps, argCount, type.asType(), argCount); + constantArgument(processor, out, deps, argCount, type.asType(), argCount, false); argCount++; } int firstArg = argCount; for (VariableElement param : params) { if (processor.getAnnotation(param, processor.getType(INJECTED_PARAMETER_CLASS_NAME)) == null) { - constantArgument(processor, out, deps, argCount, param.asType(), argCount); + constantArgument(processor, out, deps, argCount, param.asType(), argCount, false); } else { out.printf(" if (!checkInjectedArgument(b, args[%d], targetMethod)) {\n", argCount); out.printf(" return false;\n"); - out.printf(" }\n", argCount); + out.printf(" }\n"); out.printf(" %s arg%d = %s;\n", param.asType(), argCount, deps.use(processor, (DeclaredType) param.asType())); } argCount++; @@ -147,20 +157,120 @@ protected InjectedDependencies createExecute(AbstractProcessor processor, PrintW case TYPEVAR: case DECLARED: if (returnType.equals(processor.getType("java.lang.String"))) { - out.printf(" JavaConstant constant = %s.forString(result);\n", deps.use(WellKnownDependency.CONSTANT_REFLECTION)); + out.printf(" JavaConstant constant = %s.forString(result);\n", deps.use(processor, WellKnownDependency.CONSTANT_REFLECTION)); } else { - out.printf(" JavaConstant constant = %s.forObject(result);\n", deps.use(WellKnownDependency.SNIPPET_REFLECTION)); + out.printf(" JavaConstant constant = %s.forObject(result);\n", deps.use(processor, WellKnownDependency.SNIPPET_REFLECTION)); } break; default: throw new IllegalArgumentException(returnType.toString()); } - out.printf(" ConstantNode node = ConstantNode.forConstant(constant, %s, %s);\n", deps.use(WellKnownDependency.META_ACCESS), deps.use(WellKnownDependency.STRUCTURED_GRAPH)); + out.printf(" ConstantNode node = ConstantNode.forConstant(constant, %s, %s);\n", deps.use(processor, WellKnownDependency.META_ACCESS), + deps.use(processor, WellKnownDependency.STRUCTURED_GRAPH)); out.printf(" b.push(JavaKind.%s, node);\n", getReturnKind(intrinsicMethod)); out.printf(" b.notifyReplacedCall(targetMethod, node);\n"); out.printf(" return true;\n"); + } + + @Override + protected void createHelpers(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps) { + out.printf("\n"); + out.printf(" @Override\n"); + out.printf(" public boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection, Stamp stamp, NodeInputList args) {\n"); + + List params = intrinsicMethod.getParameters(); + + int argCount = 0; + Object receiver; + if (intrinsicMethod.getModifiers().contains(Modifier.STATIC)) { + receiver = intrinsicMethod.getEnclosingElement(); + } else { + receiver = "arg0"; + TypeElement type = (TypeElement) intrinsicMethod.getEnclosingElement(); + constantArgument(processor, out, deps, argCount, type.asType(), argCount, true); + argCount++; + } + + int firstArg = argCount; + for (VariableElement param : params) { + if (processor.getAnnotation(param, processor.getType(INJECTED_PARAMETER_CLASS_NAME)) == null) { + constantArgument(processor, out, deps, argCount, param.asType(), argCount, true); + } else { + out.printf(" assert args.get(%d).isNullConstant();\n", argCount); + out.printf(" %s arg%d = %s;\n", param.asType(), argCount, deps.find(processor, (DeclaredType) param.asType()).getExpression(processor, intrinsicMethod)); + } + argCount++; + } - return deps; + Set suppressWarnings = new TreeSet<>(); + if (intrinsicMethod.getAnnotation(Deprecated.class) != null) { + suppressWarnings.add("deprecation"); + } + if (hasRawtypeWarning(intrinsicMethod.getReturnType())) { + suppressWarnings.add("rawtypes"); + } + for (VariableElement param : params) { + if (hasUncheckedWarning(param.asType())) { + suppressWarnings.add("unchecked"); + } + } + if (suppressWarnings.size() > 0) { + out.printf(" @SuppressWarnings({"); + String sep = ""; + for (String suppressWarning : suppressWarnings) { + out.printf("%s\"%s\"", sep, suppressWarning); + sep = ", "; + } + out.printf("})\n"); + } + + out.printf(" %s result = %s.%s(", getErasedType(intrinsicMethod.getReturnType()), receiver, intrinsicMethod.getSimpleName()); + if (argCount > firstArg) { + out.printf("arg%d", firstArg); + for (int i = firstArg + 1; i < argCount; i++) { + out.printf(", arg%d", i); + } + } + out.printf(");\n"); + + TypeMirror returnType = intrinsicMethod.getReturnType(); + switch (returnType.getKind()) { + case BOOLEAN: + out.printf(" JavaConstant constant = JavaConstant.forInt(result ? 1 : 0);\n"); + break; + case BYTE: + case SHORT: + case CHAR: + case INT: + out.printf(" JavaConstant constant = JavaConstant.forInt(result);\n"); + break; + case LONG: + out.printf(" JavaConstant constant = JavaConstant.forLong(result);\n"); + break; + case FLOAT: + out.printf(" JavaConstant constant = JavaConstant.forFloat(result);\n"); + break; + case DOUBLE: + out.printf(" JavaConstant constant = JavaConstant.forDouble(result);\n"); + break; + case ARRAY: + case TYPEVAR: + case DECLARED: + if (returnType.equals(processor.getType("java.lang.String"))) { + out.printf(" JavaConstant constant = %s.forString(result);\n", deps.use(processor, WellKnownDependency.CONSTANT_REFLECTION)); + } else { + out.printf(" JavaConstant constant = %s.forObject(result);\n", deps.use(processor, WellKnownDependency.SNIPPET_REFLECTION)); + } + break; + default: + throw new IllegalArgumentException(returnType.toString()); + } + + out.printf(" ConstantNode node = ConstantNode.forConstant(constant, %s, %s);\n", deps.use(processor, WellKnownDependency.META_ACCESS), + deps.use(processor, WellKnownDependency.STRUCTURED_GRAPH)); + out.printf(" b.push(JavaKind.%s, node);\n", getReturnKind(intrinsicMethod)); + out.printf(" return true;\n"); + out.printf(" }\n"); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedNodeIntrinsicPlugin.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedNodeIntrinsicPlugin.java index 22e1eecdad0..1d8ecc288b0 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedNodeIntrinsicPlugin.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedNodeIntrinsicPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package org.graalvm.compiler.replacements.processor; import static org.graalvm.compiler.replacements.processor.NodeIntrinsicHandler.CONSTANT_NODE_PARAMETER_CLASS_NAME; +import static org.graalvm.compiler.replacements.processor.NodeIntrinsicHandler.FOREIGN_CALL_DESCRIPTOR_CLASS_NAME; import static org.graalvm.compiler.replacements.processor.NodeIntrinsicHandler.INJECTED_NODE_PARAMETER_CLASS_NAME; import static org.graalvm.compiler.replacements.processor.NodeIntrinsicHandler.VALUE_NODE_CLASS_NAME; @@ -58,14 +59,25 @@ protected TypeElement getAnnotationClass(AbstractProcessor processor) { return processor.getTypeElement(NodeIntrinsicHandler.NODE_INTRINSIC_CLASS_NAME); } + @Override + protected String pluginSuperclass() { + return "GeneratedNodeIntrinsicInvocationPlugin"; + } + + @Override + public void extraImports(AbstractProcessor processor, Set imports) { + imports.add("org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext"); + if (needsReplacement(processor)) { + imports.add("org.graalvm.compiler.core.common.type.Stamp"); + } + } + protected abstract List getParameters(); - protected abstract void factoryCall(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, int argCount); + protected abstract void factoryCall(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, int argCount, boolean inReplacement); @Override - protected InjectedDependencies createExecute(AbstractProcessor processor, PrintWriter out) { - InjectedDependencies deps = new InjectedDependencies(); - + protected void createExecute(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps) { List params = getParameters(); int idx = 0; @@ -80,7 +92,8 @@ protected InjectedDependencies createExecute(AbstractProcessor processor, PrintW for (int i = 0; i < signature.length; i++, idx++) { if (processor.getAnnotation(intrinsicMethod.getParameters().get(i), processor.getType(CONSTANT_NODE_PARAMETER_CLASS_NAME)) != null) { - constantArgument(processor, out, deps, idx, signature[i], i); + String argName = constantArgument(processor, out, deps, idx, signature[i], i, false); + verifyConstantArgument(out, argName, signature[i]); } else { if (signature[i].equals(processor.getType(VALUE_NODE_CLASS_NAME))) { out.printf(" ValueNode arg%d = args[%d];\n", idx, i); @@ -90,9 +103,11 @@ protected InjectedDependencies createExecute(AbstractProcessor processor, PrintW } } - factoryCall(processor, out, deps, idx); + factoryCall(processor, out, deps, idx, false); + } - return deps; + @SuppressWarnings("unused") + protected void verifyConstantArgument(PrintWriter out, String argName, TypeMirror type) { } public static class ConstructorPlugin extends GeneratedNodeIntrinsicPlugin { @@ -105,10 +120,11 @@ public ConstructorPlugin(ExecutableElement intrinsicMethod, ExecutableElement co } @Override - public void extraImports(Set imports) { + public void extraImports(AbstractProcessor processor, Set imports) { if (intrinsicMethod.getReturnType().getKind() != TypeKind.VOID) { imports.add("jdk.vm.ci.meta.JavaKind"); } + super.extraImports(processor, imports); } @Override @@ -117,7 +133,7 @@ protected List getParameters() { } @Override - protected void factoryCall(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, int argCount) { + protected void factoryCall(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, int argCount, boolean inReplacement) { out.printf(" %s node = new %s(", constructor.getEnclosingElement(), constructor.getEnclosingElement()); if (argCount > 0) { out.printf("arg0"); @@ -126,7 +142,6 @@ protected void factoryCall(AbstractProcessor processor, PrintWriter out, Injecte } } out.printf(");\n"); - if (intrinsicMethod.getReturnType().getKind() == TypeKind.VOID) { out.printf(" b.add(node);\n"); } else { @@ -145,24 +160,110 @@ public CustomFactoryPlugin(ExecutableElement intrinsicMethod, ExecutableElement this.customFactory = customFactory; } - @Override - public void extraImports(Set imports) { - } - @Override protected List getParameters() { List ret = customFactory.getParameters(); // remove initial GraphBuilderContext and ResolvedJavaMethod parameters - return ret.subList(2, ret.size()); + return ret.subList(1, ret.size()); } @Override - protected void factoryCall(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, int argCount) { - out.printf(" return %s.%s(b, targetMethod", customFactory.getEnclosingElement(), customFactory.getSimpleName()); + public void extraImports(AbstractProcessor processor, Set imports) { + if (needsReplacement(processor)) { + imports.add("org.graalvm.compiler.debug.GraalError"); + } + super.extraImports(processor, imports); + } + + @Override + protected void factoryCall(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, int argCount, boolean inReplacement) { + out.printf(" if (%s.%s(b", customFactory.getEnclosingElement(), customFactory.getSimpleName()); for (int i = 0; i < argCount; i++) { out.printf(", arg%d", i); } - out.printf(");\n"); + out.printf(")) {\n"); + out.printf(" return true;\n"); + out.printf(" }\n"); + if (needsReplacement(processor) && !inReplacement) { + out.printf(" if (b.canDeferPlugin(this)) {\n"); + out.printf(" b.replacePlugin(this, targetMethod, args, %s.FUNCTION);\n", getReplacementName()); + out.printf(" return true;\n"); + out.printf(" }\n"); + out.printf(" throw GraalError.shouldNotReachHere(\"Can't inline plugin \" + b.getClass().toString());\n"); + } else { + out.printf(" return false;\n"); + } + } + + @Override + protected void verifyConstantArgument(PrintWriter out, String argName, TypeMirror type) { + if (getErasedType(type).equals(FOREIGN_CALL_DESCRIPTOR_CLASS_NAME)) { + out.printf(" assert verifyForeignCallDescriptor(b, targetMethod, %s) : %s;\n", argName, argName); + } + } + } + + @Override + protected void createOtherClasses(AbstractProcessor processor, PrintWriter out) { + if (needsReplacement(processor)) { + super.createOtherClasses(processor, out); + } + } + + @Override + protected boolean needsReplacement(AbstractProcessor processor) { + int idx = 0; + List params = getParameters(); + for (; idx < params.size(); idx++) { + VariableElement param = params.get(idx); + if (processor.getAnnotation(param, processor.getType(INJECTED_NODE_PARAMETER_CLASS_NAME)) == null) { + break; + } + } + + for (int i = 0; i < signature.length; i++, idx++) { + if (processor.getAnnotation(intrinsicMethod.getParameters().get(i), processor.getType(CONSTANT_NODE_PARAMETER_CLASS_NAME)) != null) { + return true; + } } + return false; } + + @Override + protected void createHelpers(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps) { + if (!needsReplacement(processor)) { + return; + } + out.printf("\n"); + out.printf(" @Override\n"); + out.printf(" public boolean replace(GraphBuilderContext b, GeneratedPluginInjectionProvider injection, Stamp stamp, NodeInputList args) {\n"); + + List params = getParameters(); + + int idx = 0; + for (; idx < params.size(); idx++) { + VariableElement param = params.get(idx); + if (processor.getAnnotation(param, processor.getType(INJECTED_NODE_PARAMETER_CLASS_NAME)) == null) { + break; + } + + out.printf(" %s arg%d = %s;\n", param.asType(), idx, deps.find(processor, (DeclaredType) param.asType()).getExpression(processor, intrinsicMethod)); + } + + for (int i = 0; i < signature.length; i++, idx++) { + if (processor.getAnnotation(intrinsicMethod.getParameters().get(i), processor.getType(CONSTANT_NODE_PARAMETER_CLASS_NAME)) != null) { + constantArgument(processor, out, deps, idx, signature[i], i, true); + } else { + if (signature[i].equals(processor.getType(VALUE_NODE_CLASS_NAME))) { + out.printf(" ValueNode arg%d = args.get(%d);\n", idx, i); + } else { + out.printf(" %s arg%d = (%s) args.get(%d);\n", signature[i], idx, signature[i], i); + } + } + } + + factoryCall(processor, out, deps, idx, true); + out.printf(" }\n"); + } + } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedPlugin.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedPlugin.java index c8bd347151c..33835bf3288 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedPlugin.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/GeneratedPlugin.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ import java.io.PrintWriter; import java.util.Set; +import java.util.function.Function; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; @@ -38,7 +39,6 @@ import javax.lang.model.type.WildcardType; import org.graalvm.compiler.processor.AbstractProcessor; -import org.graalvm.compiler.replacements.processor.InjectedDependencies.Dependency; import org.graalvm.compiler.replacements.processor.InjectedDependencies.WellKnownDependency; public abstract class GeneratedPlugin { @@ -65,29 +65,57 @@ public void setPluginName(String pluginName) { this.pluginName = pluginName; } + protected String pluginSuperclass() { + return "GeneratedInvocationPlugin"; + } + public void generate(AbstractProcessor processor, PrintWriter out) { out.printf("// class: %s\n", intrinsicMethod.getEnclosingElement()); out.printf("// method: %s\n", intrinsicMethod); out.printf("// generated-by: %s\n", getClass().getName()); - out.printf("final class %s extends GeneratedInvocationPlugin {\n", pluginName); + out.printf("final class %s extends %s {\n", pluginName, pluginSuperclass()); out.printf("\n"); out.printf(" @Override\n"); out.printf(" public boolean execute(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode[] args) {\n"); out.printf(" if (!b.isPluginEnabled(this)) {\n"); out.printf(" return false;\n"); out.printf(" }\n"); - InjectedDependencies deps = createExecute(processor, out); + InjectedDependencies deps = new InjectedDependencies(true, intrinsicMethod); + createExecute(processor, out, deps); out.printf(" }\n"); out.printf(" @Override\n"); out.printf(" public Class getSource() {\n"); out.printf(" return %s.class;\n", getAnnotationClass(processor).getQualifiedName().toString().replace('$', '.')); out.printf(" }\n"); - createPrivateMembers(processor, out, deps); + createPrivateMembers(processor, out, deps, pluginName); + + out.printf("}\n"); + + createOtherClasses(processor, out); + } + + protected void createOtherClasses(AbstractProcessor processor, PrintWriter out) { + String name = getReplacementName(); + out.printf("final class %s implements PluginReplacementNode.ReplacementFunction {\n", name); + out.printf(" static PluginReplacementNode.ReplacementFunction FUNCTION = new %s();\n", name); + InjectedDependencies deps = new InjectedDependencies(false, intrinsicMethod); + createHelpers(processor, out, deps); out.printf("}\n"); } + protected abstract void createHelpers(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps); + + protected String getReplacementName() { + return "PluginReplacementNode_" + getBaseName(); + } + + private String getBaseName() { + assert getPluginName().startsWith("Plugin_"); + return getPluginName().substring("Plugin_".length()); + } + public void register(PrintWriter out) { out.printf(" plugins.register(new %s(", pluginName); if (needInjectionProvider) { @@ -103,9 +131,9 @@ public void register(PrintWriter out) { out.printf(");\n"); } - public abstract void extraImports(Set imports); + public abstract void extraImports(AbstractProcessor processor, Set imports); - protected abstract InjectedDependencies createExecute(AbstractProcessor processor, PrintWriter out); + protected abstract void createExecute(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps); static String getErasedType(TypeMirror type) { switch (type.getKind()) { @@ -161,17 +189,17 @@ static boolean hasUncheckedWarning(TypeMirror type) { } } - private void createPrivateMembers(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps) { + protected void createPrivateMembers(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, String constructorName) { if (!deps.isEmpty()) { out.printf("\n"); - for (Dependency dep : deps) { - out.printf(" private final %s %s;\n", dep.type, dep.name); + for (InjectedDependencies.Dependency dep : deps) { + out.printf(" private final %s %s;\n", dep.getType(), dep.getName(processor, intrinsicMethod)); } out.printf("\n"); - out.printf(" %s(NodeIntrinsicPluginFactory.InjectionProvider injection) {\n", pluginName); - for (Dependency dep : deps) { - out.printf(" this.%s = %s;\n", dep.name, dep.inject(processor, intrinsicMethod)); + out.printf(" %s(GeneratedPluginInjectionProvider injection) {\n", constructorName); + for (InjectedDependencies.Dependency dep : deps) { + out.printf(" this.%s = %s;\n", dep.getName(processor, intrinsicMethod), dep.getExpression(processor, intrinsicMethod)); } out.printf(" }\n"); @@ -179,6 +207,14 @@ private void createPrivateMembers(AbstractProcessor processor, PrintWriter out, } } + /** + * @param processor + * @return true if this plugin needs support for {@code PluginReplacementNode} + */ + protected boolean needsReplacement(AbstractProcessor processor) { + return true; + } + protected static String getReturnKind(ExecutableElement method) { switch (method.getReturnType().getKind()) { case BOOLEAN: @@ -204,55 +240,77 @@ protected static String getReturnKind(ExecutableElement method) { } } - protected static void constantArgument(AbstractProcessor processor, PrintWriter out, InjectedDependencies deps, int argIdx, TypeMirror type, int nodeIdx) { + protected String constantArgument(AbstractProcessor processor, + PrintWriter out, + InjectedDependencies deps, + int argIdx, + TypeMirror type, + int nodeIdx, + boolean isReplacement) { + Function argFormatter; + if (isReplacement) { + argFormatter = (i) -> String.format("args.get(%d)", i); + } else { + argFormatter = (i) -> String.format("args[%d]", i); + } if (hasRawtypeWarning(type)) { out.printf(" @SuppressWarnings({\"rawtypes\"})\n"); } - out.printf(" %s arg%d;\n", getErasedType(type), argIdx); - out.printf(" if (args[%d].isConstant()) {\n", nodeIdx); + String argName = "arg" + argIdx; + out.printf(" %s %s;\n", getErasedType(type), argName); + out.printf(" if (%s.isConstant()) {\n", argFormatter.apply(nodeIdx)); if (type.equals(processor.getType("jdk.vm.ci.meta.ResolvedJavaType"))) { - out.printf(" jdk.vm.ci.meta.JavaConstant cst = args[%d].asJavaConstant();\n", nodeIdx); - out.printf(" arg%d = %s.asJavaType(cst);\n", argIdx, deps.use(WellKnownDependency.CONSTANT_REFLECTION)); - out.printf(" if (arg%d == null) {\n", argIdx); - out.printf(" arg%d = %s.asObject(jdk.vm.ci.meta.ResolvedJavaType.class, cst);\n", argIdx, deps.use(WellKnownDependency.SNIPPET_REFLECTION)); + out.printf(" jdk.vm.ci.meta.JavaConstant cst = %s.asJavaConstant();\n", argFormatter.apply(nodeIdx)); + out.printf(" %s = %s.asJavaType(cst);\n", argName, deps.use(processor, WellKnownDependency.CONSTANT_REFLECTION)); + out.printf(" if (%s == null) {\n", argName); + out.printf(" %s = %s.asObject(jdk.vm.ci.meta.ResolvedJavaType.class, cst);\n", argName, deps.use(processor, WellKnownDependency.SNIPPET_REFLECTION)); out.printf(" }\n"); } else { switch (type.getKind()) { case BOOLEAN: - out.printf(" arg%d = args[%d].asJavaConstant().asInt() != 0;\n", argIdx, nodeIdx); + out.printf(" %s = %s.asJavaConstant().asInt() != 0;\n", argName, argFormatter.apply(nodeIdx)); break; case BYTE: - out.printf(" arg%d = (byte) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + out.printf(" %s = (byte) %s.asJavaConstant().asInt();\n", argName, argFormatter.apply(nodeIdx)); break; case CHAR: - out.printf(" arg%d = (char) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + out.printf(" %s = (char) %s.asJavaConstant().asInt();\n", argName, argFormatter.apply(nodeIdx)); break; case SHORT: - out.printf(" arg%d = (short) args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + out.printf(" %s = (short) %s.asJavaConstant().asInt();\n", argName, argFormatter.apply(nodeIdx)); break; case INT: - out.printf(" arg%d = args[%d].asJavaConstant().asInt();\n", argIdx, nodeIdx); + out.printf(" %s = %s.asJavaConstant().asInt();\n", argName, argFormatter.apply(nodeIdx)); break; case LONG: - out.printf(" arg%d = args[%d].asJavaConstant().asLong();\n", argIdx, nodeIdx); + out.printf(" %s = %s.asJavaConstant().asLong();\n", argName, argFormatter.apply(nodeIdx)); break; case FLOAT: - out.printf(" arg%d = args[%d].asJavaConstant().asFloat();\n", argIdx, nodeIdx); + out.printf(" %s = %s.asJavaConstant().asFloat();\n", argName, argFormatter.apply(nodeIdx)); break; case DOUBLE: - out.printf(" arg%d = args[%d].asJavaConstant().asDouble();\n", argIdx, nodeIdx); + out.printf(" %s = %s.asJavaConstant().asDouble();\n", argName, argFormatter.apply(nodeIdx)); break; case ARRAY: case DECLARED: - out.printf(" arg%d = %s.asObject(%s.class, args[%d].asJavaConstant());\n", argIdx, deps.use(WellKnownDependency.SNIPPET_REFLECTION), getErasedType(type), nodeIdx); + out.printf(" %s = %s.asObject(%s.class, %s.asJavaConstant());\n", argName, deps.use(processor, WellKnownDependency.SNIPPET_REFLECTION), getErasedType(type), + argFormatter.apply(nodeIdx)); break; default: throw new IllegalArgumentException(type.toString()); } } out.printf(" } else {\n"); - out.printf(" assert b.canDeferPlugin(this) : b.getClass().toString();\n"); + if (!isReplacement) { + out.printf(" if (b.shouldDeferPlugin(this)) {\n"); + out.printf(" b.replacePlugin(this, targetMethod, args, %s.FUNCTION);\n", getReplacementName()); + out.printf(" return true;\n"); + out.printf(" }\n"); + out.printf(" assert b.canDeferPlugin(this) : b.getClass().toString();\n"); + } out.printf(" return false;\n"); + out.printf(" }\n"); + return argName; } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/InjectedDependencies.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/InjectedDependencies.java index e7e65d19f9d..e0dc47038a7 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/InjectedDependencies.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/InjectedDependencies.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,50 +36,69 @@ import javax.lang.model.type.TypeMirror; import org.graalvm.compiler.processor.AbstractProcessor; -import org.graalvm.compiler.replacements.processor.InjectedDependencies.Dependency; -public class InjectedDependencies implements Iterable { +public class InjectedDependencies implements Iterable { - public abstract static class Dependency { + public interface Dependency { - public final String name; - public final String type; + String getName(AbstractProcessor processor, ExecutableElement inject); - private Dependency(String name, String type) { + String getExpression(AbstractProcessor processor, ExecutableElement inject); + + String getType(); + } + + private abstract static class DependencyImpl implements Dependency { + + private final String name; + private final String type; + + private DependencyImpl(String name, String type) { this.name = name; this.type = type; } - public abstract String inject(AbstractProcessor processor, ExecutableElement inject); + @Override + public abstract String getExpression(AbstractProcessor processor, ExecutableElement inject); + + @Override + public String getName(AbstractProcessor processor, ExecutableElement inject) { + return name; + } + + @Override + public String getType() { + return type; + } } - private static final class InjectedDependency extends Dependency { + protected static final class InjectedDependency extends DependencyImpl { - private InjectedDependency(String name, String type) { + protected InjectedDependency(String name, String type) { super(name, type); } @Override - public String inject(AbstractProcessor processor, ExecutableElement inject) { - return String.format("injection.getInjectedArgument(%s.class)", type); + public String getExpression(AbstractProcessor processor, ExecutableElement inject) { + return String.format("injection.getInjectedArgument(%s.class)", getType()); } } - private static final class InjectedStampDependency extends Dependency { + private static final class InjectedStampDependency extends DependencyImpl { private InjectedStampDependency() { super("stamp", "org.graalvm.compiler.core.common.type.Stamp"); } @Override - public String inject(AbstractProcessor processor, ExecutableElement inject) { + public String getExpression(AbstractProcessor processor, ExecutableElement inject) { AnnotationMirror nodeIntrinsic = processor.getAnnotation(inject, processor.getType(NODE_INTRINSIC_CLASS_NAME)); boolean nonNull = nodeIntrinsic != null && getAnnotationValue(nodeIntrinsic, "injectedStampIsNonNull", Boolean.class); return String.format("injection.getInjectedStamp(%s.class, %s)", GeneratedPlugin.getErasedType(inject.getReturnType()), nonNull); } } - public enum WellKnownDependency { + public enum WellKnownDependency implements Dependency { CONSTANT_REFLECTION("b.getConstantReflection()", "jdk.vm.ci.meta.ConstantReflectionProvider"), META_ACCESS("b.getMetaAccess()", "jdk.vm.ci.meta.MetaAccessProvider"), ASSUMPTIONS("b.getAssumptions()", "jdk.vm.ci.meta.Assumptions"), @@ -92,7 +111,7 @@ public enum WellKnownDependency { private final String expr; private final String type; - private final Dependency generateMember; + protected final DependencyImpl generateMember; WellKnownDependency(String expr, String type) { this.expr = expr; @@ -100,34 +119,67 @@ public enum WellKnownDependency { this.generateMember = null; } - WellKnownDependency(Dependency generateMember) { - this.expr = generateMember.name; - this.type = generateMember.type; + WellKnownDependency(DependencyImpl generateMember) { + this.expr = null; + this.type = generateMember.getType(); this.generateMember = generateMember; } - private TypeMirror getType(AbstractProcessor processor) { + protected TypeMirror getType(AbstractProcessor processor) { return processor.getType(type); } + + @Override + public String getExpression(AbstractProcessor processor, ExecutableElement inject) { + if (generateMember != null) { + return generateMember.getExpression(processor, inject); + } + return expr; + } + + @Override + public String getName(AbstractProcessor processor, ExecutableElement inject) { + if (generateMember != null) { + return generateMember.getName(processor, inject); + } + return expr; + } + + @Override + public String getType() { + if (generateMember != null) { + return generateMember.getType(); + } + return type; + } } - private final HashMap deps; + protected final HashMap deps; + protected final boolean useVariables; + protected final ExecutableElement intrinsicMethod; - public InjectedDependencies() { + public InjectedDependencies(boolean useVariables, ExecutableElement intrinsicMethod) { + this.useVariables = useVariables; + this.intrinsicMethod = intrinsicMethod; deps = new HashMap<>(); } - public String use(WellKnownDependency wellKnown) { + public String use(AbstractProcessor processor, WellKnownDependency wellKnown) { if (wellKnown.generateMember != null) { deps.put(wellKnown.type, wellKnown.generateMember); } - return wellKnown.expr; + if (useVariables) { + return wellKnown.getName(processor, intrinsicMethod) + "/* A " + wellKnown + " */"; + } else { + return wellKnown.getExpression(processor, intrinsicMethod) + "/* B " + wellKnown + " */"; + } } - public String use(AbstractProcessor processor, DeclaredType type) { + public Dependency find(AbstractProcessor processor, DeclaredType type) { for (WellKnownDependency wellKnown : WellKnownDependency.values()) { if (processor.env().getTypeUtils().isAssignable(wellKnown.getType(processor), type)) { - return use(wellKnown); + use(processor, wellKnown); + return wellKnown; } } @@ -137,7 +189,15 @@ public String use(AbstractProcessor processor, DeclaredType type) { ret = new InjectedDependency("injected" + type.asElement().getSimpleName(), typeName); deps.put(typeName, ret); } - return ret.name; + return ret; + } + + public String use(AbstractProcessor processor, DeclaredType type) { + return find(processor, type).getName(processor, intrinsicMethod); + } + + public String inject(AbstractProcessor processor, DeclaredType type) { + return find(processor, type).getExpression(processor, intrinsicMethod); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/NodeIntrinsicHandler.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/NodeIntrinsicHandler.java index d5c0cab5ad6..eab13e05e87 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/NodeIntrinsicHandler.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/NodeIntrinsicHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import static org.graalvm.compiler.processor.AbstractProcessor.getSimpleName; import java.util.ArrayList; -import java.util.Collections; import java.util.Formatter; import java.util.HashMap; import java.util.List; @@ -61,14 +60,15 @@ public final class NodeIntrinsicHandler extends AnnotationHandler { static final String MARKER_TYPE_CLASS_NAME = "org.graalvm.compiler.nodeinfo.StructuralInput.MarkerType"; static final String GRAPH_BUILDER_CONTEXT_CLASS_NAME = "org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext"; static final String STRUCTURAL_INPUT_CLASS_NAME = "org.graalvm.compiler.nodeinfo.StructuralInput"; - static final String RESOLVED_JAVA_METHOD_CLASS_NAME = "jdk.vm.ci.meta.ResolvedJavaMethod"; static final String RESOLVED_JAVA_TYPE_CLASS_NAME = "jdk.vm.ci.meta.ResolvedJavaType"; static final String VALUE_NODE_CLASS_NAME = "org.graalvm.compiler.nodes.ValueNode"; static final String STAMP_CLASS_NAME = "org.graalvm.compiler.core.common.type.Stamp"; static final String NODE_CLASS_NAME = "org.graalvm.compiler.graph.Node"; static final String NODE_INFO_CLASS_NAME = "org.graalvm.compiler.nodeinfo.NodeInfo"; static final String NODE_INTRINSIC_CLASS_NAME = "org.graalvm.compiler.graph.Node.NodeIntrinsic"; + static final String NODE_INTRINSIC_FACTORY_CLASS_NAME = "org.graalvm.compiler.graph.Node.NodeIntrinsicFactory"; static final String INJECTED_NODE_PARAMETER_CLASS_NAME = "org.graalvm.compiler.graph.Node.InjectedNodeParameter"; + static final String FOREIGN_CALL_DESCRIPTOR_CLASS_NAME = "org.graalvm.compiler.core.common.spi.ForeignCallDescriptor"; public NodeIntrinsicHandler(AbstractProcessor processor) { super(processor, NODE_INTRINSIC_CLASS_NAME); @@ -111,6 +111,7 @@ public void process(Element element, AnnotationMirror annotation, PluginGenerato } boolean injectedStampIsNonNull = getAnnotationValue(annotation, "injectedStampIsNonNull", Boolean.class); + boolean isFactory = processor.getAnnotation(nodeClass, processor.getType(NODE_INTRINSIC_FACTORY_CLASS_NAME)) != null; if (returnType.getKind() == TypeKind.VOID) { for (VariableElement parameter : intrinsicMethod.getParameters()) { @@ -120,54 +121,83 @@ public void process(Element element, AnnotationMirror annotation, PluginGenerato } } } + Formatter msg = new Formatter(); + List factories = findIntrinsifyFactoryMethods(nodeClass); + if (factories.size() > 0) { + boolean hadError = false; + if (isFactory) { + for (ExecutableElement candidate : factories) { + String error = checkIntrinsifyFactorySignature(candidate); + if (error != null) { + messager.printMessage(Kind.ERROR, msg.format("intrinsify method has invalid signature: %s%n%s", error, candidate).toString(), candidate); + hadError = true; + } + } + } else { + for (ExecutableElement candidate : factories) { + messager.printMessage(Kind.ERROR, String.format("Found intrinsify methods in %s which is not a NodeIntrinsicFactory", nodeClass), candidate); + hadError = true; + } + } + if (hadError) { + return; + } + } TypeMirror[] constructorSignature = constructorSignature(intrinsicMethod); Map nonMatches = new HashMap<>(); - List factories = findIntrinsifyFactoryMethod(nodeClass, constructorSignature, nonMatches, injectedStampIsNonNull); - List constructors = Collections.emptyList(); - if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) { - if (factories.isEmpty()) { - messager.printMessage(Kind.ERROR, String.format("Cannot make a node intrinsic for abstract class %s.", nodeClass.getSimpleName()), element, annotation); + if (isFactory) { + List candidates = findIntrinsifyFactoryMethods(factories, constructorSignature, nonMatches, injectedStampIsNonNull); + if (checkTooManyElements(annotation, intrinsicMethod, messager, nodeClass, "factories", candidates, msg)) { + return; } - } else if (!isNodeType(nodeClass)) { - if (factories.isEmpty()) { - messager.printMessage(Kind.ERROR, String.format("%s is not a subclass of %s.", nodeClass.getSimpleName(), processor.getType(NODE_CLASS_NAME)), element, annotation); + if (candidates.size() == 1) { + generator.addPlugin(new GeneratedNodeIntrinsicPlugin.CustomFactoryPlugin(intrinsicMethod, candidates.get(0), constructorSignature)); + return; } } else { - TypeMirror ret = returnType; - if (processor.env().getTypeUtils().isAssignable(ret, processor.getType(STRUCTURAL_INPUT_CLASS_NAME))) { - checkInputType(nodeClass, ret, element, annotation); + if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) { + messager.printMessage(Kind.ERROR, String.format("Cannot make a node intrinsic for abstract class %s.", nodeClass.getSimpleName()), element, annotation); + return; + } else if (!isNodeType(nodeClass)) { + messager.printMessage(Kind.ERROR, String.format("%s is not a subclass of %s.", nodeClass.getSimpleName(), processor.getType(NODE_CLASS_NAME)), element, annotation); + return; + } + if (processor.env().getTypeUtils().isAssignable(returnType, processor.getType(STRUCTURAL_INPUT_CLASS_NAME))) { + checkInputType(nodeClass, returnType, element, annotation); } - constructors = findConstructors(nodeClass, constructorSignature, nonMatches, injectedStampIsNonNull); + List constructors = findConstructors(nodeClass, constructorSignature, nonMatches, injectedStampIsNonNull); + if (checkTooManyElements(annotation, intrinsicMethod, messager, nodeClass, "constructors", constructors, msg)) { + return; + } + if (constructors.size() == 1) { + generator.addPlugin(new GeneratedNodeIntrinsicPlugin.ConstructorPlugin(intrinsicMethod, constructors.get(0), constructorSignature)); + return; + } } - Formatter msg = new Formatter(); - if (factories.size() > 1) { - msg.format("Found more than one factory in %s matching node intrinsic:", nodeClass); - for (ExecutableElement candidate : factories) { - msg.format("%n %s", candidate); + String label = isFactory ? "factories" : "constructors"; + msg.format("Could not find any %s in %s matching node intrinsic", label, nodeClass); + if (!nonMatches.isEmpty()) { + msg.format("%nThese %s failed to match:", label); + for (Map.Entry e : nonMatches.entrySet()) { + msg.format("%n %s: %s", e.getKey(), e.getValue()); } - messager.printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation); - } else if (constructors.size() > 1) { - msg.format("Found more than one constructor in %s matching node intrinsic:", nodeClass); - for (ExecutableElement candidate : constructors) { + } + messager.printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation); + } + + private static boolean checkTooManyElements(AnnotationMirror annotation, ExecutableElement intrinsicMethod, Messager messager, TypeElement nodeClass, String kind, List elements, + Formatter msg) { + if (elements.size() > 1) { + msg.format("Found more than one %s in %s matching node intrinsic:", kind, nodeClass); + for (ExecutableElement candidate : elements) { msg.format("%n %s", candidate); } messager.printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation); - } else if (factories.size() == 1) { - generator.addPlugin(new GeneratedNodeIntrinsicPlugin.CustomFactoryPlugin(intrinsicMethod, factories.get(0), constructorSignature)); - } else if (constructors.size() == 1) { - generator.addPlugin(new GeneratedNodeIntrinsicPlugin.ConstructorPlugin(intrinsicMethod, constructors.get(0), constructorSignature)); - } else { - msg.format("Could not find any factories or constructors in %s matching node intrinsic", nodeClass); - if (!nonMatches.isEmpty()) { - msg.format("%nFactories and constructors that failed to match:"); - for (Map.Entry e : nonMatches.entrySet()) { - msg.format("%n %s: %s", e.getKey(), e.getValue()); - } - } - messager.printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation); + return true; } + return false; } private void checkInputType(TypeElement nodeClass, TypeMirror returnType, Element element, AnnotationMirror annotation) { @@ -236,42 +266,46 @@ private List findConstructors(TypeElement nodeClass, TypeMirr return found; } - private List findIntrinsifyFactoryMethod(TypeElement nodeClass, TypeMirror[] signature, Map nonMatches, boolean requiresInjectedStamp) { - List methods = ElementFilter.methodsIn(nodeClass.getEnclosedElements()); - List found = new ArrayList<>(methods.size()); - for (ExecutableElement method : methods) { - if (!method.getSimpleName().toString().equals("intrinsify")) { - continue; - } + private String checkIntrinsifyFactorySignature(ExecutableElement method) { + if (method.getParameters().size() < 1) { + return "Too few arguments"; + } - if (method.getParameters().size() < 2) { - nonMatches.put(method, "Too few arguments"); - continue; - } + VariableElement firstArg = method.getParameters().get(0); + if (!isTypeCompatible(firstArg.asType(), processor.getType(GRAPH_BUILDER_CONTEXT_CLASS_NAME))) { + return "First argument isn't of type GraphBuilderContext"; + } - VariableElement firstArg = method.getParameters().get(0); - if (!isTypeCompatible(firstArg.asType(), processor.getType(GRAPH_BUILDER_CONTEXT_CLASS_NAME))) { - nonMatches.put(method, "First argument isn't of type GraphBuilderContext"); - continue; - } + if (method.getReturnType().getKind() != TypeKind.BOOLEAN) { + return "Doesn't return boolean"; + } - VariableElement secondArg = method.getParameters().get(1); - if (!isTypeCompatible(secondArg.asType(), processor.getType(RESOLVED_JAVA_METHOD_CLASS_NAME))) { - nonMatches.put(method, "Second argument isn't of type ResolvedJavaMethod"); - continue; - } + if (!method.getModifiers().contains(Modifier.STATIC)) { + return "Method is non-static"; + } - if (method.getReturnType().getKind() != TypeKind.BOOLEAN) { - nonMatches.put(method, "Doesn't return boolean"); - continue; - } + if (!method.getModifiers().contains(Modifier.PUBLIC)) { + return "Method is non-public"; + } + return null; + } - if (!method.getModifiers().contains(Modifier.STATIC)) { - nonMatches.put(method, "Method is non-static"); - continue; + private static List findIntrinsifyFactoryMethods(TypeElement nodeClass) { + List methods = ElementFilter.methodsIn(nodeClass.getEnclosedElements()); + List found = new ArrayList<>(1); + for (ExecutableElement method : methods) { + if (method.getSimpleName().toString().equals("intrinsify")) { + found.add(method); } + } + return found; + } - if (matchSignature(2, method, signature, nonMatches, requiresInjectedStamp)) { + private List findIntrinsifyFactoryMethods(List intrinsifyFactoryMethods, TypeMirror[] signature, Map nonMatches, + boolean requiresInjectedStamp) { + List found = new ArrayList<>(1); + for (ExecutableElement method : intrinsifyFactoryMethods) { + if (matchSignature(1, method, signature, nonMatches, requiresInjectedStamp)) { found.add(method); } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/PluginGenerator.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/PluginGenerator.java index 1b9ac95af3a..1c2810e818d 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/PluginGenerator.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.processor/src/org/graalvm/compiler/replacements/processor/PluginGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; @@ -122,40 +123,47 @@ private static void createPluginFactory(AbstractProcessor processor, Element top out.printf("// GENERATORS: %s, %s\n", ReplacementsAnnotationProcessor.class.getName(), PluginGenerator.class.getName()); out.printf("package %s;\n", pkg.getQualifiedName()); out.printf("\n"); - createImports(out, plugins); + createImports(out, processor, plugins); out.printf("\n"); for (GeneratedPlugin plugin : plugins) { plugin.generate(processor, out); out.printf("\n"); } - out.printf("public class %s implements NodeIntrinsicPluginFactory {\n", genClassName); + out.printf("public class %s implements GeneratedPluginFactory {\n", genClassName); createPluginFactoryMethod(out, plugins); out.printf("}\n"); } } catch (IOException e) { processor.env().getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage()); } - processor.createProviderFile(qualifiedGenClassName, "org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory", topLevelClass); + processor.createProviderFile(qualifiedGenClassName, "org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginFactory", topLevelClass); } - protected static void createImports(PrintWriter out, List plugins) { - out.printf("import jdk.vm.ci.meta.ResolvedJavaMethod;\n"); - out.printf("\n"); - out.printf("import java.lang.annotation.Annotation;\n"); - out.printf("import org.graalvm.compiler.nodes.ValueNode;\n"); - out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;\n"); - out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedInvocationPlugin;\n"); - out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;\n"); - out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;\n"); - out.printf("import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;\n"); - + protected static void createImports(PrintWriter out, AbstractProcessor processor, List plugins) { HashSet extra = new HashSet<>(); + + extra.add("jdk.vm.ci.meta.ResolvedJavaMethod"); + extra.add("java.lang.annotation.Annotation"); + extra.add("org.graalvm.compiler.nodes.ValueNode"); + extra.add("org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext"); + extra.add("org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin"); + extra.add("org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins"); + extra.add("org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginFactory"); + extra.add("org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider"); + for (GeneratedPlugin plugin : plugins) { - plugin.extraImports(extra); + plugin.extraImports(processor, extra); + extra.add("org.graalvm.compiler.nodes.graphbuilderconf." + plugin.pluginSuperclass()); + if (plugin.needsReplacement(processor)) { + extra.add("org.graalvm.compiler.graph.NodeInputList"); + extra.add("org.graalvm.compiler.nodes.PluginReplacementNode"); + } } if (!extra.isEmpty()) { out.printf("\n"); - for (String i : extra) { + String[] imports = extra.toArray(new String[extra.size()]); + Arrays.sort(imports); + for (String i : imports) { out.printf("import %s;\n", i); } } @@ -163,7 +171,7 @@ protected static void createImports(PrintWriter out, List plugi private static void createPluginFactoryMethod(PrintWriter out, List plugins) { out.printf(" @Override\n"); - out.printf(" public void registerPlugins(InvocationPlugins plugins, NodeIntrinsicPluginFactory.InjectionProvider injection) {\n"); + out.printf(" public void registerPlugins(InvocationPlugins plugins, GeneratedPluginInjectionProvider injection) {\n"); for (GeneratedPlugin plugin : plugins) { plugin.register(out); } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java index a40840c63f2..a4a1f3bfd4b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/FoldTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,9 +32,9 @@ import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; -import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory.InjectionProvider; import org.graalvm.compiler.replacements.NodeIntrinsificationProvider; import org.junit.Test; @@ -81,7 +81,7 @@ public static int test() { @Override protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { - InjectionProvider injection = new NodeIntrinsificationProvider(getMetaAccess(), getSnippetReflection(), getProviders().getForeignCalls(), null, getTarget()); + GeneratedPluginInjectionProvider injection = new NodeIntrinsificationProvider(getMetaAccess(), getSnippetReflection(), getProviders().getForeignCalls(), null, getTarget()); new PluginFactory_FoldTest().registerPlugins(invocationPlugins, injection); BytecodeProvider replacementBytecodeProvider = getSystemClassLoaderBytecodeProvider(); Registration r = new Registration(invocationPlugins, TestMethod.class, getReplacements(), replacementBytecodeProvider); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java index d17ddf293d6..a276a1b8a63 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java @@ -31,6 +31,8 @@ import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.EncodedGraph; +import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValueNode; @@ -48,6 +50,7 @@ import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.replacements.CachingPEGraphDecoder; import jdk.internal.vm.compiler.word.LocationIdentity; +import org.junit.Assert; import org.junit.Test; import jdk.vm.ci.meta.JavaKind; @@ -127,18 +130,62 @@ public InlineInfo shouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod m } } + public interface SingleInterface { + SingleInterface increment(long offset); + } + + static class SingleInterfaceImpl implements SingleInterface { + + int counter; + + @Override + public SingleInterfaceImpl increment(long offset) { + counter++; + return this; + } + + static void init() { + } + } + + @BytecodeParserNeverInline + static SingleInterface doIncrement(SingleInterface ptr) { + return ptr.increment(0); + } + + static void testSingleImplementorDevirtualize(SingleInterface ptr) { + doIncrement(ptr); + } + + @Test + public void testSingleImplementor() { + EconomicMap graphCache = EconomicMap.create(); + // Parse and cache doIncrement before the single implementor is loaded + test("doIncrement", graphCache); + // Force loading of the single implementor + SingleInterfaceImpl.init(); + StructuredGraph graph = test("testSingleImplementorDevirtualize", graphCache); + Assert.assertEquals(0, graph.getNodes().filter(InvokeNode.class).count()); + } + @Test @SuppressWarnings("try") public void test() { - ResolvedJavaMethod testMethod = getResolvedJavaMethod(PEGraphDecoderTest.class, "doTest", Object.class); + test("doTest", EconomicMap.create()); + } + + @SuppressWarnings("try") + private StructuredGraph test(String methodName, EconomicMap graphCache) { + ResolvedJavaMethod testMethod = getResolvedJavaMethod(methodName); StructuredGraph targetGraph = null; DebugContext debug = getDebugContext(); try (DebugContext.Scope scope = debug.scope("GraphPETest", testMethod)) { GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withEagerResolving(true).withUnresolvedIsError(true); + graphBuilderConfig = editGraphBuilderConfiguration(graphBuilderConfig); registerPlugins(graphBuilderConfig.getPlugins().getInvocationPlugins()); - targetGraph = new StructuredGraph.Builder(getInitialOptions(), debug, AllowAssumptions.YES).method(testMethod).build(); + targetGraph = new StructuredGraph.Builder(debug.getOptions(), debug, AllowAssumptions.YES).method(testMethod).build(); CachingPEGraphDecoder decoder = new CachingPEGraphDecoder(getTarget().arch, targetGraph, getProviders(), graphBuilderConfig, OptimisticOptimizations.NONE, AllowAssumptions.YES, - null, null, new InlineInvokePlugin[]{new InlineAll()}, null, null, null, null, null, EconomicMap.create()); + null, null, new InlineInvokePlugin[]{new InlineAll()}, null, null, null, null, null, graphCache); decoder.decode(testMethod, false, false); debug.dump(DebugContext.BASIC_LEVEL, targetGraph, "Target Graph"); @@ -147,12 +194,12 @@ public void test() { CoreProviders context = getProviders(); createCanonicalizerPhase().apply(targetGraph, context); targetGraph.verify(); - + return targetGraph; } catch (Throwable ex) { if (targetGraph != null) { debug.dump(DebugContext.BASIC_LEVEL, targetGraph, ex.toString()); } - debug.handle(ex); + throw debug.handle(ex); } } } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java index 3d93f510df0..2666e09af60 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java @@ -51,12 +51,12 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.OpaqueNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; -import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.CanonicalizerPhase; @@ -322,7 +322,7 @@ public static void nonVoidIntrinsicWithCallStub(int zLen) { protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { BytecodeProvider replacementBytecodeProvider = getSystemClassLoaderBytecodeProvider(); Registration r = new Registration(invocationPlugins, TestObject.class, getReplacements(), replacementBytecodeProvider); - NodeIntrinsicPluginFactory.InjectionProvider injections = new DummyInjectionProvider(); + GeneratedPluginInjectionProvider injections = new DummyInjectionProvider(); new PluginFactory_ReplacementsParseTest().registerPlugins(invocationPlugins, injections); r.registerMethodSubstitution(TestObjectSubstitutions.class, "nextAfter", double.class, double.class); r.registerMethodSubstitution(TestObjectSubstitutions.class, "stringize", Object.class); @@ -649,7 +649,7 @@ private void testGraph(String name) { } } - private class DummyInjectionProvider implements NodeIntrinsicPluginFactory.InjectionProvider { + private class DummyInjectionProvider implements GeneratedPluginInjectionProvider { @SuppressWarnings("unchecked") @Override public T getInjectedArgument(Class type) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java index b4cc33e9558..eee756efbfb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java @@ -235,7 +235,7 @@ public void test() { } private static boolean isInNativeImage(String className) { - return className.startsWith("org.graalvm.nativeimage"); + return className.startsWith("jdk.internal.vm.compiler.nativeimage"); } private static boolean isGSON(String className) { diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java index 2ad11a2e5ee..1d4ab5aecf5 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ConstantStringIndexOfSnippets.java @@ -26,10 +26,11 @@ import static org.graalvm.compiler.nodes.util.ConstantReflectionUtil.loadByteArrayConstant; import static org.graalvm.compiler.nodes.util.ConstantReflectionUtil.loadCharArrayConstant; +import static org.graalvm.compiler.replacements.ReplacementsUtil.byteArrayBaseOffset; +import static org.graalvm.compiler.replacements.ReplacementsUtil.charArrayBaseOffset; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe; -import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; @@ -191,16 +192,6 @@ static long computeCacheUtf16(MetaAccessProvider metaAccess, byte[] s) { return cache; } - @Fold - static int byteArrayBaseOffset(@InjectedParameter MetaAccessProvider metaAccess) { - return metaAccess.getArrayBaseOffset(JavaKind.Byte); - } - - @Fold - static int charArrayBaseOffset(@InjectedParameter MetaAccessProvider metaAccess) { - return metaAccess.getArrayBaseOffset(JavaKind.Char); - } - /** Marker value for the {@link InjectedParameter} injected parameter. */ static final MetaAccessProvider INJECTED = null; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/MethodHandlePlugin.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/MethodHandlePlugin.java index 10e2c25fad0..ad565989849 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/MethodHandlePlugin.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/MethodHandlePlugin.java @@ -30,6 +30,7 @@ import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodes.CallTargetNode; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; +import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; @@ -110,8 +111,13 @@ public T add(T node) { return false; } - b.handleReplacedInvoke(invoke.getInvokeKind(), targetMethod, argumentsList.toArray(new ValueNode[argumentsList.size()]), inlineEverything); - + Invoke newInvoke = b.handleReplacedInvoke(invoke.getInvokeKind(), targetMethod, argumentsList.toArray(new ValueNode[argumentsList.size()]), inlineEverything); + if (newInvoke != null && !newInvoke.callTarget().equals(invoke.callTarget()) && newInvoke.asFixedNode().isAlive()) { + // In the case where the invoke is not inlined, replace its call target with the + // special ResolvedMethodHandleCallTargetNode. + newInvoke.callTarget().replaceAndDelete(b.append(invoke.callTarget())); + return true; + } /* * After handleReplacedInvoke, a return type according to the signature of * targetMethod has been pushed. That can be different than the type expected by the diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java index 719abcf9b5d..e4cc75d32ef 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/NodeIntrinsificationProvider.java @@ -30,7 +30,7 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory.InjectionProvider; +import org.graalvm.compiler.nodes.graphbuilderconf.GeneratedPluginInjectionProvider; import org.graalvm.compiler.replacements.arraycopy.ArrayCopyForeignCalls; import org.graalvm.compiler.word.WordTypes; @@ -39,7 +39,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaType; -public class NodeIntrinsificationProvider implements InjectionProvider { +public class NodeIntrinsificationProvider implements GeneratedPluginInjectionProvider { public static final TargetDescription INJECTED_TARGET = null; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java index 61005f7a7ac..0a8cf2eefae 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java @@ -82,6 +82,7 @@ import org.graalvm.compiler.nodes.MergeNode; import org.graalvm.compiler.nodes.NodeView; import org.graalvm.compiler.nodes.ParameterNode; +import org.graalvm.compiler.nodes.PluginReplacementNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.SimplifyingGraphDecoder; import org.graalvm.compiler.nodes.StateSplit; @@ -568,6 +569,66 @@ public GraphBuilderContext getNonIntrinsicAncestor() { } } + protected class PEPluginGraphBuilderContext extends PENonAppendGraphBuilderContext { + protected FixedWithNextNode insertBefore; + protected ValueNode pushedNode; + + public PEPluginGraphBuilderContext(PEMethodScope inlineScope, FixedWithNextNode insertBefore) { + super(inlineScope, inlineScope.invokeData != null ? inlineScope.invokeData.invoke : null); + this.insertBefore = insertBefore; + } + + @Override + public void push(JavaKind kind, ValueNode value) { + if (pushedNode != null) { + throw unimplemented("Only one push is supported"); + } + pushedNode = value; + } + + @Override + public void setStateAfter(StateSplit sideEffect) { + assert sideEffect.hasSideEffect(); + FrameState stateAfter = getGraph().add(new FrameState(BytecodeFrame.BEFORE_BCI)); + sideEffect.setStateAfter(stateAfter); + } + + @SuppressWarnings("try") + @Override + public T append(T v) { + if (v.graph() != null) { + return v; + } + try (DebugCloseable position = withNodeSoucePosition()) { + T added = getGraph().addOrUniqueWithInputs(v); + if (added == v) { + updateLastInstruction(v); + } + return added; + } + } + + private DebugCloseable withNodeSoucePosition() { + if (getGraph().trackNodeSourcePosition()) { + NodeSourcePosition callerBytecodePosition = methodScope.getCallerBytecodePosition(); + if (callerBytecodePosition != null) { + return getGraph().withNodeSourcePosition(callerBytecodePosition); + } + } + return null; + } + + private void updateLastInstruction(T value) { + if (value instanceof FixedWithNextNode) { + FixedWithNextNode fixed = (FixedWithNextNode) value; + graph.addBeforeFixed(insertBefore, fixed); + } else if (value instanceof FixedNode) { + // Block terminating fixed nodes shouldn't be inserted + throw GraalError.shouldNotReachHere(); + } + } + } + @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED, allowedUsageTypes = {InputType.Value, InputType.Guard, InputType.Anchor}) static class ExceptionPlaceholderNode extends ValueNode { public static final NodeClass TYPE = NodeClass.create(ExceptionPlaceholderNode.class); @@ -670,7 +731,7 @@ public void decode(ResolvedJavaMethod method, boolean isSubstitution, boolean tr /* Check that the control flow graph can be computed, to catch problems early. */ assert CFGVerifier.verify(ControlFlowGraph.compute(graph, true, true, true, true)); } catch (Throwable ex) { - throw GraalError.shouldNotReachHere("Control flow graph not valid after partial evaluation"); + throw GraalError.shouldNotReachHere(ex, "Control flow graph not valid after partial evaluation"); } } @@ -778,6 +839,7 @@ protected LoopScope handleInvoke(MethodScope s, LoopScope loopScope, InvokeData if (methodCall.invokeKind().hasReceiver()) { invokeData.constantReceiver = methodCall.arguments().get(0).asJavaConstant(); } + callTarget = trySimplifyCallTarget(methodScope, invokeData, (MethodCallTargetNode) callTarget); LoopScope inlineLoopScope = trySimplifyInvoke(methodScope, loopScope, invokeData, (MethodCallTargetNode) callTarget); if (inlineLoopScope != null) { return inlineLoopScope; @@ -790,14 +852,23 @@ protected LoopScope handleInvoke(MethodScope s, LoopScope loopScope, InvokeData return super.handleInvoke(methodScope, loopScope, invokeData); } - protected LoopScope trySimplifyInvoke(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) { + protected MethodCallTargetNode trySimplifyCallTarget(PEMethodScope methodScope, InvokeData invokeData, MethodCallTargetNode callTarget) { // attempt to devirtualize the call ResolvedJavaMethod specialCallTarget = getSpecialCallTarget(invokeData, callTarget); if (specialCallTarget != null) { callTarget.setTargetMethod(specialCallTarget); callTarget.setInvokeKind(InvokeKind.Special); + return callTarget; + } + if (callTarget.invokeKind().isInterface()) { + Invoke invoke = invokeData.invoke; + ResolvedJavaType contextType = methodScope.method.getDeclaringClass(); + return MethodCallTargetNode.tryDevirtualizeInterfaceCall(callTarget.receiver(), callTarget.targetMethod(), null, graph.getAssumptions(), contextType, callTarget, invoke.asNode()); } + return callTarget; + } + protected LoopScope trySimplifyInvoke(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) { if (tryInvocationPlugin(methodScope, loopScope, invokeData, callTarget)) { /* * The invocation plugin handled the call, so decoding continues in the calling method. @@ -1318,10 +1389,25 @@ protected Node canonicalizeFixedNode(MethodScope s, Node node) { } } } + if (node instanceof PluginReplacementNode) { + PluginReplacementNode pluginReplacementNode = (PluginReplacementNode) node; + PEPluginGraphBuilderContext graphBuilderContext = new PEPluginGraphBuilderContext(methodScope, + pluginReplacementNode); + boolean success = pluginReplacementNode.replace(graphBuilderContext, providers.getReplacements()); + if (success) { + replacedNode = graphBuilderContext.pushedNode; + } else if (pluginReplacementMustSucceed()) { + throw new GraalError("Plugin failed:" + node); + } + } return super.canonicalizeFixedNode(methodScope, replacedNode); } + protected boolean pluginReplacementMustSucceed() { + return false; + } + @Override protected Node handleFloatingNodeBeforeAdd(MethodScope s, LoopScope loopScope, Node n) { PEMethodScope methodScope = (PEMethodScope) s; diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java index 1fb3e568770..ab32164deb7 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java @@ -52,6 +52,10 @@ import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugContext.Builder; @@ -89,10 +93,13 @@ import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.compiler.replacements.arraycopy.ArrayCopyForeignCalls; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordOperationPlugin; +import org.graalvm.compiler.word.WordTypes; import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; @@ -135,6 +142,43 @@ public GraphBuilderConfiguration.Plugins getGraphBuilderPlugins() { return graphBuilderPlugins; } + @SuppressWarnings("unchecked") + @Override + public T getInjectedArgument(Class capability) { + if (capability.equals(TargetDescription.class)) { + return (T) target; + } + if (capability.equals(ForeignCallsProvider.class)) { + return (T) getProviders().getForeignCalls(); + } + if (capability.equals(ArrayCopyForeignCalls.class) && getProviders().getForeignCalls() instanceof ArrayCopyForeignCalls) { + return (T) getProviders().getForeignCalls(); + } + if (capability.equals(SnippetReflectionProvider.class)) { + return (T) snippetReflection; + } + if (capability.isAssignableFrom(WordTypes.class)) { + return (T) getProviders().getWordTypes(); + } + throw GraalError.shouldNotReachHere(capability.toString()); + } + + @Override + public Stamp getInjectedStamp(Class type, boolean nonNull) { + JavaKind kind = JavaKind.fromJavaClass(type); + if (kind == JavaKind.Object) { + ResolvedJavaType returnType = providers.getMetaAccess().lookupJavaType(type); + WordTypes wordTypes = getProviders().getWordTypes(); + if (wordTypes.isWord(returnType)) { + return wordTypes.getWordStamp(returnType); + } else { + return StampFactory.object(TypeReference.createWithoutAssumptions(returnType), nonNull); + } + } else { + return StampFactory.forKind(kind); + } + } + @Override public Class getIntrinsifyingPlugin(ResolvedJavaMethod method) { if (!IS_IN_NATIVE_IMAGE) { @@ -222,13 +266,17 @@ public ReplacementsImpl(DebugHandlersFactory debugHandlersFactory, Providers pro public DebugContext openDebugContext(String idPrefix, ResolvedJavaMethod method, OptionValues options) { if (DebugStubsAndSnippets.getValue(options)) { - DebugContext outer = DebugContext.forCurrentThread(); - Description description = new Description(method, idPrefix + nextDebugContextId.incrementAndGet()); - return new Builder(options, debugHandlersFactory).globalMetrics(outer.getGlobalMetrics()).description(description).build(); + return openSnippetDebugContext(idPrefix, method, options); } return DebugContext.disabled(options); } + public DebugContext openSnippetDebugContext(String idPrefix, ResolvedJavaMethod method, OptionValues options) { + DebugContext outer = DebugContext.forCurrentThread(); + Description description = new Description(method, idPrefix + nextDebugContextId.incrementAndGet()); + return new Builder(options, debugHandlersFactory).globalMetrics(outer.getGlobalMetrics()).description(description).build(); + } + @Override @SuppressWarnings("try") public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, @@ -468,7 +516,7 @@ protected void finalizeGraph(StructuredGraph graph) { if (!GraalOptions.SnippetCounters.getValue(graph.getOptions()) || graph.getNodes().filter(SnippetCounterNode.class).isEmpty()) { int sideEffectCount = 0; assert (sideEffectCount = graph.getNodes().filter(e -> hasSideEffect(e)).count()) >= 0; - new ConvertDeoptimizeToGuardPhase().apply(graph, null); + new ConvertDeoptimizeToGuardPhase().apply(graph, replacements.getProviders()); assert sideEffectCount == graph.getNodes().filter(e -> hasSideEffect(e)).count() : "deleted side effecting node"; new DeadCodeEliminationPhase(Required).apply(graph); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsUtil.java index 274250725b5..59074e371c9 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsUtil.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsUtil.java @@ -77,4 +77,24 @@ public static int getArrayBaseOffset(@InjectedParameter MetaAccessProvider metaA return metaAccessProvider.getArrayBaseOffset(elementKind); } + @Fold + public static int charArrayBaseOffset(@InjectedParameter MetaAccessProvider metaAccess) { + return metaAccess.getArrayBaseOffset(JavaKind.Char); + } + + @Fold + public static int charArrayIndexScale(@InjectedParameter MetaAccessProvider metaAccess) { + return metaAccess.getArrayIndexScale(JavaKind.Char); + } + + @Fold + public static int byteArrayBaseOffset(@InjectedParameter MetaAccessProvider metaAccess) { + return metaAccess.getArrayBaseOffset(JavaKind.Byte); + } + + @Fold + public static int byteArrayIndexScale(@InjectedParameter MetaAccessProvider metaAccess) { + return metaAccess.getArrayIndexScale(JavaKind.Byte); + } + } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java index 6fe5e7b5d56..0e07ff94c2e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java @@ -703,18 +703,6 @@ protected boolean removeEldestEntry(java.util.Map.Entry eldest) { private static final Object UNUSED_PARAMETER = "UNUSED_PARAMETER"; private static final Object CONSTANT_PARAMETER = "CONSTANT_PARAMETER"; - /** - * Determines if any parameter of a given method is annotated with {@link ConstantParameter}. - */ - public static boolean hasConstantParameter(ResolvedJavaMethod method) { - for (ConstantParameter p : method.getParameterAnnotations(ConstantParameter.class)) { - if (p != null) { - return true; - } - } - return false; - } - private final SnippetReflectionProvider snippetReflection; /** diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java index 0c9e6671400..678d8f007eb 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/gc/G1WriteBarrierSnippets.java @@ -216,7 +216,7 @@ public void g1PostWriteBarrier(Address address, Object object, Object value, @Co if (probability(FREQUENT_PROBABILITY, writtenValue.notEqual(0))) { // Calculate the address of the card to be enqueued to the // thread local card queue. - Word cardAddress = cardTableAddress().add(oop.unsignedShiftRight(cardTableShift())); + Word cardAddress = cardTableAddress(oop); byte cardByte = cardAddress.readByte(0, GC_CARD_LOCATION); counters.g1EffectiveAfterNullPostWriteBarrierCounter.inc(); @@ -296,10 +296,8 @@ public void g1ArrayRangePostWriteBarrier(Address address, int length, @ConstantP Word indexAddress = thread.add(cardQueueIndexOffset()); long indexValue = thread.readWord(cardQueueIndexOffset(), CARD_QUEUE_INDEX_LOCATION).rawValue(); - int cardShift = cardTableShift(); - Word cardStart = cardTableAddress(); - Word start = cardStart.add(getPointerToFirstArrayElement(address, length, elementStride).unsignedShiftRight(cardShift)); - Word end = cardStart.add(getPointerToLastArrayElement(address, length, elementStride).unsignedShiftRight(cardShift)); + Word start = cardTableAddress(getPointerToFirstArrayElement(address, length, elementStride)); + Word end = cardTableAddress(getPointerToLastArrayElement(address, length, elementStride)); Word cur = start; do { @@ -348,9 +346,7 @@ public void g1ArrayRangePostWriteBarrier(Address address, int length, @ConstantP protected abstract byte youngCardValue(); - protected abstract Word cardTableAddress(); - - protected abstract int cardTableShift(); + protected abstract Word cardTableAddress(Pointer oop); protected abstract int logOfHeapRegionGrainBytes(); diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/CStringConstant.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/CStringConstant.java index 4497e1a61ab..ade93b88a9b 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/CStringConstant.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/CStringConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,17 +31,18 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; +import org.graalvm.compiler.graph.Node.NodeIntrinsicFactory; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.word.Word; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Represents a compile-time constant zero-terminated UTF-8 string installed with the generated * code. */ +@NodeIntrinsicFactory public final class CStringConstant extends DataPointerConstant { private static final Charset UTF8 = Charset.forName("utf8"); @@ -71,7 +72,7 @@ public String toValueString() { return "c\"" + string + "\""; } - public static boolean intrinsify(GraphBuilderContext b, @SuppressWarnings("unused") ResolvedJavaMethod targetMethod, String string) { + public static boolean intrinsify(GraphBuilderContext b, String string) { b.addPush(JavaKind.Object, new ConstantNode(new CStringConstant(string), StampFactory.pointer())); return true; } diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java index ad4b389f486..d1ff81cbb0e 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java @@ -53,7 +53,9 @@ protected CacheEntry(ValueNode object, T identity) { @Override public int hashCode() { int result = 31 + ((identity == null) ? 0 : identity.hashCode()); - return 31 * result + ((object == null) ? 0 : object.hashCode()); + // we need to use the identity hash code for the object since the node may not yet have + // a valid id and thus not have a stable hash code + return 31 * result + ((object == null) ? 0 : System.identityHashCode(object)); } @Override diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java index 6f88f558761..2c3428e7be8 100644 --- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java +++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java @@ -511,7 +511,7 @@ public ValueNode convert(GraphBuilderContext b, ValueNode value, JavaKind toKind return b.add(new NarrowNode(value, 32)); } else { assert toKind == JavaKind.Long; - assert value.getStackKind() == JavaKind.Int; + assert value.getStackKind() == JavaKind.Int : value; if (unsigned) { return b.add(new ZeroExtendNode(value, 64)); } else { diff --git a/src/jdk.internal.vm.compiler/s