diff --git a/.hgtags b/.hgtags index 1fa938d529c..c8669af3d81 100644 --- a/.hgtags +++ b/.hgtags @@ -381,3 +381,4 @@ e384420383a5b79fa0012ebcb25d8f83cff7f777 jdk-9+135 1b4b5d01aa11edf24b6fadbe3d2f3e411e3b02cd jdk-9+136 9cb87c88ed851c0575b8ead753ea238ed5b544e9 jdk-9+137 d273dfe9a126d3bffe92072547fef2cd1361b0eb jdk-9+138 +65477538bec32963dc41153d89c4417eb46c45fc jdk-9+139 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 5fdee3f6017..ec2e8625423 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -381,3 +381,4 @@ be1218f792a450dfb5d4b1f82616b9d95a6a732e jdk-9+133 3ec350f5f32af249b59620d7e37b54bdcd77b233 jdk-9+136 d7f519b004254b19e384131d9f0d0e40e31a0fd3 jdk-9+137 67c4388142bdf58aec8fefa4475faaa8a5d7380c jdk-9+138 +7dcf453eacae79ee86a6bcc75fd0b546fc99b48a jdk-9+139 diff --git a/ASSEMBLY_EXCEPTION b/ASSEMBLY_EXCEPTION index 8b7ac1d0813..065b8d90239 100644 --- a/ASSEMBLY_EXCEPTION +++ b/ASSEMBLY_EXCEPTION @@ -1,27 +1,27 @@ OPENJDK ASSEMBLY EXCEPTION -The OpenJDK source code made available by Sun at openjdk.java.net and -openjdk.dev.java.net ("OpenJDK Code") is distributed under the terms of the -GNU General Public License version 2 +The OpenJDK source code made available by Oracle America, Inc. (Oracle) at +openjdk.java.net ("OpenJDK Code") is distributed under the terms of the GNU +General Public License version 2 only ("GPL2"), with the following clarification and special exception. Linking this OpenJDK Code statically or dynamically with other code is making a combined work based on this library. Thus, the terms and conditions of GPL2 cover the whole combination. - As a special exception, Sun gives you permission to link this - OpenJDK Code with certain code licensed by Sun as indicated at + As a special exception, Oracle gives you permission to link this + OpenJDK Code with certain code licensed by Oracle as indicated at http://openjdk.java.net/legal/exception-modules-2007-05-08.html ("Designated Exception Modules") to produce an executable, regardless of the license terms of the Designated Exception Modules, and to copy and distribute the resulting executable under GPL2, provided that the Designated Exception Modules continue to be - governed by the licenses under which they were offered by Sun. + governed by the licenses under which they were offered by Oracle. -As such, it allows licensees and sublicensees of Sun's GPL2 OpenJDK Code to -build an executable that includes those portions of necessary code that Sun -could not provide under GPL2 (or that Sun has provided under GPL2 with the -Classpath exception). If you modify or add to the OpenJDK code, that new -GPL2 code may still be combined with Designated Exception Modules if the -new code is made subject to this exception by its copyright holder. +As such, it allows licensees and sublicensees of Oracle's GPL2 OpenJDK Code +to build an executable that includes those portions of necessary code that +Oracle could not provide under GPL2 (or that Oracle has provided under GPL2 +with the Classpath exception). If you modify or add to the OpenJDK code, +that new GPL2 code may still be combined with Designated Exception Modules +if the new code is made subject to this exception by its copyright holder. diff --git a/common/bin/compare.sh b/common/bin/compare.sh index a54f1d4197c..21c9051e426 100644 --- a/common/bin/compare.sh +++ b/common/bin/compare.sh @@ -654,10 +654,10 @@ compare_bin_file() { OTHER_DIZ_FILE="$OTHER/support/native/java.base/java_objs/java.diz" elif [ "$NAME" = "jimage.exe" ] \ && [ -f "$OTHER/support/native/jdk.jlink/jimage_objs/jimage.diz" ]; then - OTHER_DIZ_FILE="$OTHER/support/native/jdk.jlink/jimage_objs/jimage.diz" + OTHER_DIZ_FILE="$OTHER/support/modules_cmds/jdk.jlink/jimage.diz" elif [ "$NAME" = "javacpl.exe" ] \ && [ -f "$OTHER/support/native/jdk.plugin/javacpl/javacpl.diz" ]; then - OTHER_DIZ_FILE="$OTHER/support/native/jdk.plugin/javacpl/javacpl.diz" + OTHER_DIZ_FILE="$OTHER/support/modules_cmds/jdk.deploy.controlpanel/javacpl.diz" elif [ -f "${OTHER_FILE_BASE}.diz" ]; then OTHER_DIZ_FILE=${OTHER_FILE_BASE}.diz else @@ -686,10 +686,10 @@ compare_bin_file() { THIS_DIZ_FILE="$THIS/support/native/java.base/java_objs/java.diz" elif [ "$NAME" = "jimage.exe" ] \ && [ -f "$THIS/support/native/jdk.jlink/jimage_objs/jimage.diz" ]; then - THIS_DIZ_FILE="$THIS/support/native/jdk.jlink/jimage_objs/jimage.diz" + THIS_DIZ_FILE="$THIS/support/modules_cmds/jdk.jlink/jimage.diz" elif [ "$NAME" = "javacpl.exe" ] \ && [ -f "$THIS/support/native/jdk.plugin/javacpl/javacpl.diz" ]; then - THIS_DIZ_FILE="$THIS/support/native/jdk.plugin/javacpl/javacpl.diz" + THIS_DIZ_FILE="$THIS/support/modules_cmds/jdk.deploy.controlpanel/javacpl.diz" elif [ -f "${THIS_FILE_BASE}.diz" ]; then THIS_DIZ_FILE=${THIS_FILE/.dll/}.diz else diff --git a/corba/.hgtags b/corba/.hgtags index 46f6d728864..c5bbcbce5a7 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -381,3 +381,4 @@ f7e1d5337c2e550fe553df7a3886bbed80292ecd jdk-9+131 aa053a3faf266c12b4fd5272da431a3e08e4a3e3 jdk-9+136 258cf18fa7fc59359b874f8743b7168dc48baf73 jdk-9+137 27bb44be32076861a0951bcefb07a1d92509a4b6 jdk-9+138 +8c9da7fc5b07c606afd571c7012441b77dda83b2 jdk-9+139 diff --git a/corba/ASSEMBLY_EXCEPTION b/corba/ASSEMBLY_EXCEPTION index 8b7ac1d0813..065b8d90239 100644 --- a/corba/ASSEMBLY_EXCEPTION +++ b/corba/ASSEMBLY_EXCEPTION @@ -1,27 +1,27 @@ OPENJDK ASSEMBLY EXCEPTION -The OpenJDK source code made available by Sun at openjdk.java.net and -openjdk.dev.java.net ("OpenJDK Code") is distributed under the terms of the -GNU General Public License version 2 +The OpenJDK source code made available by Oracle America, Inc. (Oracle) at +openjdk.java.net ("OpenJDK Code") is distributed under the terms of the GNU +General Public License version 2 only ("GPL2"), with the following clarification and special exception. Linking this OpenJDK Code statically or dynamically with other code is making a combined work based on this library. Thus, the terms and conditions of GPL2 cover the whole combination. - As a special exception, Sun gives you permission to link this - OpenJDK Code with certain code licensed by Sun as indicated at + As a special exception, Oracle gives you permission to link this + OpenJDK Code with certain code licensed by Oracle as indicated at http://openjdk.java.net/legal/exception-modules-2007-05-08.html ("Designated Exception Modules") to produce an executable, regardless of the license terms of the Designated Exception Modules, and to copy and distribute the resulting executable under GPL2, provided that the Designated Exception Modules continue to be - governed by the licenses under which they were offered by Sun. + governed by the licenses under which they were offered by Oracle. -As such, it allows licensees and sublicensees of Sun's GPL2 OpenJDK Code to -build an executable that includes those portions of necessary code that Sun -could not provide under GPL2 (or that Sun has provided under GPL2 with the -Classpath exception). If you modify or add to the OpenJDK code, that new -GPL2 code may still be combined with Designated Exception Modules if the -new code is made subject to this exception by its copyright holder. +As such, it allows licensees and sublicensees of Oracle's GPL2 OpenJDK Code +to build an executable that includes those portions of necessary code that +Oracle could not provide under GPL2 (or that Oracle has provided under GPL2 +with the Classpath exception). If you modify or add to the OpenJDK code, +that new GPL2 code may still be combined with Designated Exception Modules +if the new code is made subject to this exception by its copyright holder. diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 02397a6cce1..bfddfeea0ac 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -541,3 +541,4 @@ b8b694c6b4d2ab0939aed7adaf0eec1ac321a085 jdk-9+134 a20da289f646ee44440695b81abc0548330e4ca7 jdk-9+136 dfcbf839e299e7e2bba1da69bdb347617ea4c7e8 jdk-9+137 fc0956308c7a586267c5dd35dff74f773aa9c3eb jdk-9+138 +08492e67bf3226784dab3bf9ae967382ddbc1af5 jdk-9+139 diff --git a/hotspot/ASSEMBLY_EXCEPTION b/hotspot/ASSEMBLY_EXCEPTION index 3e78398d906..065b8d90239 100644 --- a/hotspot/ASSEMBLY_EXCEPTION +++ b/hotspot/ASSEMBLY_EXCEPTION @@ -1,9 +1,9 @@ OPENJDK ASSEMBLY EXCEPTION -The OpenJDK source code made available by Oracle at openjdk.java.net and -openjdk.dev.java.net ("OpenJDK Code") is distributed under the terms of the -GNU General Public License version 2 +The OpenJDK source code made available by Oracle America, Inc. (Oracle) at +openjdk.java.net ("OpenJDK Code") is distributed under the terms of the GNU +General Public License version 2 only ("GPL2"), with the following clarification and special exception. Linking this OpenJDK Code statically or dynamically with other code @@ -19,9 +19,9 @@ only ("GPL2"), with the following clarification and special exception. provided that the Designated Exception Modules continue to be governed by the licenses under which they were offered by Oracle. -As such, it allows licensees and sublicensees of Oracle's GPL2 OpenJDK Code to -build an executable that includes those portions of necessary code that Oracle -could not provide under GPL2 (or that Oracle has provided under GPL2 with the -Classpath exception). If you modify or add to the OpenJDK code, that new -GPL2 code may still be combined with Designated Exception Modules if the -new code is made subject to this exception by its copyright holder. +As such, it allows licensees and sublicensees of Oracle's GPL2 OpenJDK Code +to build an executable that includes those portions of necessary code that +Oracle could not provide under GPL2 (or that Oracle has provided under GPL2 +with the Classpath exception). If you modify or add to the OpenJDK code, +that new GPL2 code may still be combined with Designated Exception Modules +if the new code is made subject to this exception by its copyright holder. diff --git a/hotspot/make/BuildHotspot.gmk b/hotspot/make/BuildHotspot.gmk index 4ae7b84c387..0ac43f6283c 100644 --- a/hotspot/make/BuildHotspot.gmk +++ b/hotspot/make/BuildHotspot.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -45,10 +45,7 @@ $(VARIANT_TARGETS): variant-%: variant-%-gensrc variant-%-libs jsig: +$(MAKE) -f lib/CompileLibjsig.gmk -dist: $(VARIANT_TARGETS) jsig - +$(MAKE) -f Dist.gmk - -all: dist +all: $(VARIANT_TARGETS) jsig .PHONY: $(VARIANT_TARGETS) $(VARIANT_GENSRC_TARGETS) $(VARIANT_LIBS_TARGETS) \ - jsig dist all + jsig all diff --git a/hotspot/make/CopyToExplodedJdk.gmk b/hotspot/make/CopyToExplodedJdk.gmk new file mode 100644 index 00000000000..3219d572529 --- /dev/null +++ b/hotspot/make/CopyToExplodedJdk.gmk @@ -0,0 +1,55 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Copy all built libraries into exploded jdk +LIB_TARGETS := $(filter $(LIB_OUTPUTDIR)/%, $(TARGETS)) +ifeq ($(OPENJDK_TARGET_OS), windows) + $(eval $(call SetupCopyFiles, COPY_LIBS_BIN, \ + SRC := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base, \ + DEST := $(JDK_OUTPUTDIR)/bin, \ + FILES := $(filter-out %.lib, $(LIB_TARGETS)), \ + )) + + $(eval $(call SetupCopyFiles, COPY_LIBS_LIB, \ + SRC := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base, \ + DEST := $(JDK_OUTPUTDIR)/lib, \ + FILES := $(filter %.lib, $(LIB_TARGETS)))) + + TARGETS += $(COPY_LIBS_BIN) $(COPY_LIBS_LIB) +else + $(eval $(call SetupCopyFiles, COPY_LIBS, \ + SRC := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base, \ + DEST := $(JDK_OUTPUTDIR)/lib, \ + FILES := $(filter %$(SHARED_LIBRARY_SUFFIX), $(LIB_TARGETS)), \ + )) + $(eval $(call SetupCopyFiles, LINK_LIBS, \ + SRC := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base, \ + DEST := $(JDK_OUTPUTDIR)/lib, \ + FILES := $(filter-out %$(SHARED_LIBRARY_SUFFIX), $(LIB_TARGETS)), \ + MACRO := link-file-relative, \ + )) + + TARGETS += $(COPY_LIBS) $(LINK_LIBS) +endif diff --git a/hotspot/make/Dist.gmk b/hotspot/make/Dist.gmk deleted file mode 100644 index 710de55960c..00000000000 --- a/hotspot/make/Dist.gmk +++ /dev/null @@ -1,223 +0,0 @@ -# -# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -################################################################################ -# Copy the generated output into well-defined places in the dist directory. - -# This must be the first rule -default: all - -include $(SPEC) -include MakeBase.gmk - -$(eval $(call IncludeCustomExtension, hotspot, Dist.gmk)) - -DIST_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/dist - -# Unfortunately, all platforms have different target subdirs. -ifeq ($(OPENJDK_TARGET_OS), windows) - LIB_SUBDIR := bin -else ifeq ($(OPENJDK_TARGET_OS), macosx) - LIB_SUBDIR := lib -else - LIB_SUBDIR := lib$(OPENJDK_TARGET_CPU_LIBDIR) -endif - -################################################################################ -# Setup make rules to copy a native library and associated data. -# -# Parameter 1 is the name of the rule. This name is used as variable prefix, -# and the targets generated are listed in a variable by that name. -# -# Remaining parameters are named arguments. These include: -# NAME -- The base name of the native library (e.g. 'jvm') -# VARIANT -- The variant to copy from -# VARIANT_TARGET_DIR -- The variant target sub dir, with trailing slash, optional -SetupDistLibFile = $(NamedParamsMacroTemplate) -define SetupDistLibFileBody - ifneq ($$($1_VARIANT), ) - $1_SRC_DIR := $$(HOTSPOT_OUTPUTDIR)/variant-$$($1_VARIANT)/lib$$($1_NAME) - else - $1_SRC_DIR := $$(HOTSPOT_OUTPUTDIR)/lib$$($1_NAME) - endif - $1_LIB_NAME := $(LIBRARY_PREFIX)$$($1_NAME) - $1_TARGET_DIR := $$(DIST_OUTPUTDIR)/$$(LIB_SUBDIR)/$$($1_VARIANT_TARGET_DIR) - - # Copy the the native library. - $$(eval $$(call SetupCopyFiles, $1_COPY_LIB, \ - DEST := $$($1_TARGET_DIR), \ - FILES := $$(wildcard \ - $$($1_SRC_DIR)/$$($1_LIB_NAME)$(SHARED_LIBRARY_SUFFIX)), \ - )) - - TARGETS += $$($1_COPY_LIB) - - # Copy related data (debug symbols, static-build symbols file etc) - $$(eval $$(call SetupCopyFiles, $1_COPY_FILES, \ - DEST := $$($1_TARGET_DIR), \ - FILES := $$(wildcard \ - $$(addprefix $$($1_SRC_DIR)/$$($1_LIB_NAME), \ - .diz .debuginfo .pdb .map .symbols)), \ - )) - - TARGETS += $$($1_COPY_FILES) - - ifeq ($(OPENJDK_TARGET_OS), macosx) - # Debug symbols on macosx is a directory, not a single file, per library. - $1_DSYM_SRC := $$($1_SRC_DIR)/$$($1_LIB_NAME)$(SHARED_LIBRARY_SUFFIX).dSYM) - ifneq ($$(wildcard $$($1_DSYM_SRC)), ) - $$(eval $$(call SetupCopyFiles, $1_COPY_DSYM_DIR, \ - DEST := $$($1_TARGET_DIR), \ - SRC := $$($1_SRC_DIR), \ - FILES := $$(shell $(FIND) $$($1_DSYM_SRC) -type f), \ - )) - TARGETS += $$($1_COPY_DSYM_DIR) - endif - endif -endef - -################################################################################ -# Copy common files, which are independent on the jvm variant(s) being built. -# For files that were generated during the build, we assume all versions of -# these files are identical, and just pick one arbitrarily to use as source. - -ANY_JVM_VARIANT := $(firstword $(JVM_VARIANTS)) -JVM_VARIANT_OUTPUTDIR := $(HOTSPOT_OUTPUTDIR)/variant-$(ANY_JVM_VARIANT) - -### Copy platform-independent .h files -INCLUDE_FILES_SRC_DIR := $(HOTSPOT_TOPDIR)/src/share/vm -$(eval $(call SetupCopyFiles, COPY_INCLUDE, \ - SRC := $(INCLUDE_FILES_SRC_DIR), \ - DEST := $(DIST_OUTPUTDIR)/include, \ - FLATTEN := true, \ - FILES := $(INCLUDE_FILES_SRC_DIR)/prims/jni.h \ - $(INCLUDE_FILES_SRC_DIR)/code/jvmticmlr.h \ - $(INCLUDE_FILES_SRC_DIR)/services/jmm.h)) - -TARGETS += $(COPY_INCLUDE) - -### Copy jni_md.h - -# This might have been defined in a custom extension -ifeq ($(JNI_MD_H_SRC), ) - JNI_MD_H_SRC := $(HOTSPOT_TOPDIR)/src/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/vm/jni_$(HOTSPOT_TARGET_CPU_ARCH).h -endif - -ifeq ($(OPENJDK_TARGET_OS), macosx) - # NOTE: This should most likely be darwin, but the old hotspot build uses bsd - JNI_MD_SUBDIR := bsd -else ifeq ($(OPENJDK_TARGET_OS), windows) - JNI_MD_SUBDIR := win32 -else - JNI_MD_SUBDIR := $(OPENJDK_TARGET_OS) -endif - -# SetupCopyFiles is not used here since it's non-trivial to copy a single -# file with a different target name. -$(DIST_OUTPUTDIR)/include/$(JNI_MD_SUBDIR)/jni_md.h: $(JNI_MD_H_SRC) - $(call LogInfo, Copying hotspot/dist/include/$(JNI_MD_SUBDIR)/jni_md.h) - $(install-file) - -TARGETS += $(DIST_OUTPUTDIR)/include/$(JNI_MD_SUBDIR)/jni_md.h - -$(eval $(call SetupCopyFiles, COPY_JVMTI_H, \ - DEST := $(DIST_OUTPUTDIR)/include, \ - FLATTEN := true, \ - FILES := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles/jvmti.h)) - -TARGETS += $(COPY_JVMTI_H) - -# NOTE: In the old build, this file was not copied on Windows. -ifneq ($(OPENJDK_TARGET_OS), windows) - $(eval $(call SetupCopyFiles, COPY_JVMTI_HTML, \ - DEST := $(DIST_OUTPUTDIR)/docs/platform/jvmti, \ - FILES := $(JVM_VARIANT_OUTPUTDIR)/gensrc/jvmtifiles/jvmti.html)) -endif - -TARGETS += $(COPY_JVMTI_HTML) - -ifeq ($(OPENJDK_TARGET_OS), windows) - $(eval $(call SetupCopyFiles, COPY_JVM_LIB, \ - DEST := $(DIST_OUTPUTDIR)/lib, \ - FILES :=$(JVM_VARIANT_OUTPUTDIR)/libjvm/objs/jvm.lib)) - - TARGETS += $(COPY_JVM_LIB) -endif - -# Copy libjsig, if it exists -$(eval $(call SetupDistLibFile, DIST_jsig, \ - NAME := jsig, \ -)) - -################################################################################ -# Copy variant-specific files - -# Setup make rules to copy a single variant to dist. -# $1: The name of the variant -define SetupDistForVariant - ifneq ($$(filter client minimal, $1), ) - VARIANT_TARGET_DIR := $1 - else - # Use 'server' as default target directory name for all other variants. - VARIANT_TARGET_DIR := server - endif - - $$(eval $$(call SetupDistLibFile, DIST_$(strip $1)_jvm, \ - NAME := jvm, \ - VARIANT := $1, \ - VARIANT_TARGET_DIR := $$(VARIANT_TARGET_DIR)/, \ - )) - - # Copy the dtrace libraries, if they exist - $$(eval $$(call SetupDistLibFile, DIST_$(strip $1)_jvm_db, \ - NAME := jvm_db, \ - VARIANT := $1, \ - VARIANT_TARGET_DIR := $$(VARIANT_TARGET_DIR)/, \ - )) - - $$(eval $$(call SetupDistLibFile, DIST_$(strip $1)_jvm_dtrace, \ - NAME := jvm_dtrace, \ - VARIANT := $1, \ - VARIANT_TARGET_DIR := $$(VARIANT_TARGET_DIR)/, \ - )) - - # Copy the Xusage.txt file - $$(eval $$(call SetupCopyFiles, DIST_$(strip $1)_Xusage, \ - DEST := $$(DIST_OUTPUTDIR)/$$(LIB_SUBDIR)/$(strip $1), \ - FILES := $$(HOTSPOT_OUTPUTDIR)/variant-$(strip $1)/support/misc/Xusage.txt, \ - )) - - TARGETS += $$(DIST_$(strip $1)_Xusage) -endef - -$(foreach variant, $(JVM_VARIANTS), \ - $(eval $(call SetupDistForVariant, $(variant))) \ -) - -################################################################################ - -all: $(TARGETS) - -.PHONY: all diff --git a/hotspot/make/HotspotCommon.gmk b/hotspot/make/HotspotCommon.gmk index 1df3f4fa9b3..239478cae76 100644 --- a/hotspot/make/HotspotCommon.gmk +++ b/hotspot/make/HotspotCommon.gmk @@ -33,6 +33,15 @@ JVM_SUPPORT_DIR := $(JVM_VARIANT_OUTPUTDIR)/support DTRACE_SUPPORT_DIR := $(JVM_SUPPORT_DIR)/dtrace +LIB_OUTPUTDIR := $(call FindLibDirForModule, java.base) +ifneq ($(filter client minimal, $(JVM_VARIANT)), ) + JVM_VARIANT_SUBDIR := $(JVM_VARIANT) +else + # Use 'server' as default target directory name for all other variants. + JVM_VARIANT_SUBDIR := server +endif +JVM_LIB_OUTPUTDIR := $(LIB_OUTPUTDIR)/$(JVM_VARIANT_SUBDIR) + ################################################################################ # Test if a feature is available in the present build of JVM_VARIANT. Will return diff --git a/hotspot/make/copy/Copy-java.base.gmk b/hotspot/make/copy/Copy-java.base.gmk new file mode 100644 index 00000000000..ffb6e30dae5 --- /dev/null +++ b/hotspot/make/copy/Copy-java.base.gmk @@ -0,0 +1,67 @@ +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# These include files are currently being copied from the jdk repository for +# historical reasons. Disable copying from here until this has been cleaned up. +# The files in hotspot differ slightly from the corresponding files in jdk. +# See JDK-8167078. + +INCLUDE_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_include/$(MODULE) + +################################################################################ +# Copy platform-independent .h files +$(eval $(call SetupCopyFiles, COPY_INCLUDE_FILES, \ + SRC := $(HOTSPOT_TOPDIR)/src/share/vm, \ + DEST := $(INCLUDE_DST_DIR), \ + FLATTEN := true, \ + FILES := prims/jni.h code/jvmticmlr.h \ +)) + +#TARGETS += $(COPY_INCLUDE_FILES) + +################################################################################ +# Copy jni_md.h + +# This might have been defined in a custom extension +JNI_MD_H_SRC ?= $(HOTSPOT_TOPDIR)/src/cpu/$(HOTSPOT_TARGET_CPU_ARCH)/vm/jni_$(HOTSPOT_TARGET_CPU_ARCH).h + +ifeq ($(OPENJDK_TARGET_OS), macosx) + # NOTE: This should most likely be darwin, but the old hotspot build uses bsd + JNI_MD_SUBDIR := bsd +else ifeq ($(OPENJDK_TARGET_OS), windows) + JNI_MD_SUBDIR := win32 +else + JNI_MD_SUBDIR := $(OPENJDK_TARGET_OS) +endif + +# SetupCopyFiles is not used here since it's non-trivial to copy a single +# file with a different target name. +$(INCLUDE_DST_DIR)/$(JNI_MD_SUBDIR)/jni_md.h: $(JNI_MD_H_SRC) + $(call LogInfo, Copying hotspot/dist/include/$(JNI_MD_SUBDIR)/jni_md.h) + $(install-file) + +#TARGETS += $(INCLUDE_DST_DIR)/$(JNI_MD_SUBDIR)/jni_md.h + +################################################################################ diff --git a/hotspot/make/gensrc/GenerateSources.gmk b/hotspot/make/gensrc/GenerateSources.gmk index b91f2d0c864..31c342ae83e 100644 --- a/hotspot/make/gensrc/GenerateSources.gmk +++ b/hotspot/make/gensrc/GenerateSources.gmk @@ -47,7 +47,7 @@ $(eval $(call IncludeCustomExtension, hotspot, gensrc/GenerateSources.gmk)) # The Xusage.txt file needs to have platform specific path separator $(eval $(call SetupTextFileProcessing, CREATE_XUSAGE, \ SOURCE_FILES := $(HOTSPOT_TOPDIR)/src/share/vm/Xusage.txt, \ - OUTPUT_FILE := $(JVM_SUPPORT_DIR)/misc/Xusage.txt, \ + OUTPUT_FILE := $(JVM_LIB_OUTPUTDIR)/Xusage.txt, \ REPLACEMENTS := separated by ;> => separated by $(PATH_SEP)> ; , \ )) diff --git a/hotspot/make/gensrc/GensrcJvmti.gmk b/hotspot/make/gensrc/GensrcJvmti.gmk index 25f569dc119..323c7e93da8 100644 --- a/hotspot/make/gensrc/GensrcJvmti.gmk +++ b/hotspot/make/gensrc/GensrcJvmti.gmk @@ -67,7 +67,8 @@ define SetupXslTransformBody $$($1_OUTPUT_DIR)/$1: $$($1_XML_FILE) $$($1_XSL_FILE) $$($1_DEPS) $$(BUILD_JVMTI_TOOLS) $$(call LogInfo, Generating $$(@F)) $$(call MakeDir, $$(@D)) - $$(call ExecuteWithLog, $$@, $$(TOOL_JVMTI_GEN) -IN $$($1_XML_FILE) -XSL $$($1_XSL_FILE) -OUT $$@ $$($1_ARGS)) + $$(call ExecuteWithLog, $$@, $$(TOOL_JVMTI_GEN) -IN $$($1_XML_FILE) \ + -XSL $$($1_XSL_FILE) -OUT $$@ $$($1_ARGS)) # jvmtiGen does not return error code properly on fail. # NOTE: We should really fix jvmtiGen.java instead. test -f $$@ @@ -128,14 +129,29 @@ $(JVMTI_OUTPUTDIR)/jvmtiEnvRecommended.cpp: $(JVMTI_SRCDIR)/jvmtiEnv.cpp \ TARGETS += $(JVMTI_OUTPUTDIR)/jvmtiEnvRecommended.cpp +################################################################################ +# Disable copy of jvmti.h from hotspot until this has been cleared up. The file +# is currently being copied from the jdk repository. See JDK-8167078. +# Copy jvmti.h to include dir + +# The file is the same regardless of jvm variant. Only let one do the copy. +#ifeq ($(JVM_VARIANT), $(firstword $(JVM_VARIANTS))) +# $(eval $(call SetupCopyFiles, COPY_JVMTI_H, \ +# DEST := $(SUPPORT_OUTPUTDIR)/modules_include/java.base, \ +# FILES := $(JVMTI_OUTPUTDIR)/jvmti.h, \ +# )) + +# TARGETS += $(COPY_JVMTI_H) +#endif + ################################################################################ # Create trace files in gensrc/tracefiles TRACE_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/tracefiles TRACE_SRCDIR := $(HOTSPOT_TOPDIR)/src/share/vm/trace -# Append directories to search (might have been set by custom extensions) -TRACE_SEARCH_DIRS += $(TRACE_SRCDIR) +# Append list of XSL files to search (might have been set by custom extensions) +TRACE_XSL_FILES += $(wildcard $(TRACE_SRCDIR)/*.xsl) TRACE_XML ?= $(TRACE_SRCDIR)/trace.xml @@ -155,7 +171,7 @@ TRACE_DEPS += \ define SetupTraceGeneration $$(eval $$(call SetupXslTransform, $1, \ XML_FILE := $$(TRACE_XML), \ - XSL_FILE := $$(firstword $$(wildcard $$(addsuffix /$$(basename $1).xsl, $$(TRACE_SEARCH_DIRS)))), \ + XSL_FILE := $$(firstword $$(filter %/$$(basename $1).xsl, $$(TRACE_XSL_FILES))), \ OUTPUT_DIR := $$(TRACE_OUTPUTDIR), \ DEPS := $$(TRACE_DEPS), \ )) diff --git a/hotspot/make/lib/CompileDtracePostJvm.gmk b/hotspot/make/lib/CompileDtracePostJvm.gmk index 45c81ad9c4e..6b98014e18c 100644 --- a/hotspot/make/lib/CompileDtracePostJvm.gmk +++ b/hotspot/make/lib/CompileDtracePostJvm.gmk @@ -180,7 +180,7 @@ ifeq ($(call check-jvm-feature, dtrace), true) $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DTRACE, \ LIBRARY := jvm_dtrace, \ - OUTPUT_DIR := $(LIBJVM_DTRACE_OUTPUTDIR), \ + OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \ SRC := $(HOTSPOT_TOPDIR)/src/os/solaris/dtrace, \ INCLUDE_FILES := jvm_dtrace.c, \ CFLAGS := -m64 -G -mt -KPIC, \ @@ -197,7 +197,7 @@ ifeq ($(call check-jvm-feature, dtrace), true) # the old build. $(eval $(call SetupNativeCompilation, BUILD_LIBJVM_DB, \ LIBRARY := jvm_db, \ - OUTPUT_DIR := $(LIBJVM_DB_OUTPUTDIR), \ + OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \ SRC := $(HOTSPOT_TOPDIR)/src/os/solaris/dtrace, \ INCLUDE_FILES := libjvm_db.c, \ CFLAGS := -I$(JVM_VARIANT_OUTPUTDIR)/gensrc -I$(DTRACE_SUPPORT_DIR) \ diff --git a/hotspot/make/lib/CompileJvm.gmk b/hotspot/make/lib/CompileJvm.gmk index 6901fc27d76..07fddfbaf35 100644 --- a/hotspot/make/lib/CompileJvm.gmk +++ b/hotspot/make/lib/CompileJvm.gmk @@ -174,13 +174,6 @@ ifeq ($(OPENJDK_TARGET_OS), windows) JVM_RCFLAGS += -D"HS_FILEDESC=$(HOTSPOT_VM_DISTRO) $(RC_DESC)$(JVM_VARIANT) VM" endif -ifeq ($(OPENJDK_TARGET_OS), macosx) - # NOTE: The old build did not strip binaries on macosx. - JVM_STRIP_SYMBOLS := false -else - JVM_STRIP_SYMBOLS := true -endif - JVM_OPTIMIZATION ?= HIGHEST_JVM ################################################################################ @@ -189,7 +182,7 @@ JVM_OPTIMIZATION ?= HIGHEST_JVM $(eval $(call SetupNativeCompilation, BUILD_LIBJVM, \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ LIBRARY := jvm, \ - OUTPUT_DIR := $(JVM_OUTPUTDIR), \ + OUTPUT_DIR := $(JVM_LIB_OUTPUTDIR), \ SRC := $(JVM_SRC_DIRS), \ EXCLUDES := $(JVM_EXCLUDES), \ EXCLUDE_FILES := $(JVM_EXCLUDE_FILES), \ @@ -211,7 +204,6 @@ $(eval $(call SetupNativeCompilation, BUILD_LIBJVM, \ OBJECT_DIR := $(JVM_OUTPUTDIR)/objs, \ MAPFILE := $(JVM_MAPFILE), \ USE_MAPFILE_FOR_SYMBOLS := true, \ - STRIP_SYMBOLS := $(JVM_STRIP_SYMBOLS), \ EMBED_MANIFEST := true, \ RC_FLAGS := $(JVM_RCFLAGS), \ VERSIONINFO_RESOURCE := $(HOTSPOT_TOPDIR)/src/os/windows/vm/version.rc, \ @@ -219,6 +211,18 @@ $(eval $(call SetupNativeCompilation, BUILD_LIBJVM, \ PRECOMPILED_HEADER_EXCLUDE := $(JVM_PRECOMPILED_HEADER_EXCLUDE), \ )) +ifeq ($(OPENJDK_TARGET_OS), windows) + # It doesn't matter which jvm.lib file gets exported, but we need + # to pick just one. + ifeq ($(JVM_VARIANT), $(firstword $(JVM_VARIANTS))) + $(eval $(call SetupCopyFiles, COPY_JVM_LIB, \ + DEST := $(LIB_OUTPUTDIR), \ + FILES :=$(JVM_VARIANT_OUTPUTDIR)/libjvm/objs/jvm.lib, \ + )) + TARGETS += $(COPY_JVM_LIB) + endif +endif + # AIX warning explanation: # 1500-010 : (W) WARNING in ...: Infinite loop. Program may not stop. # There are several infinite loops in the vm, so better suppress. diff --git a/hotspot/make/lib/CompileLibjsig.gmk b/hotspot/make/lib/CompileLibjsig.gmk index 1c9a10fbf5c..52c2896b190 100644 --- a/hotspot/make/lib/CompileLibjsig.gmk +++ b/hotspot/make/lib/CompileLibjsig.gmk @@ -34,7 +34,6 @@ include NativeCompilation.gmk ifneq ($(OPENJDK_TARGET_OS), windows) ifeq ($(STATIC_BUILD), false) - LIBJSIG_STRIP_SYMBOLS := true ifeq ($(OPENJDK_TARGET_OS), linux) LIBJSIG_CFLAGS := -fPIC -D_GNU_SOURCE -D_REENTRANT $(EXTRA_CFLAGS) LIBJSIG_LDFLAGS := $(LDFLAGS_HASH_STYLE) $(EXTRA_CFLAGS) @@ -72,8 +71,6 @@ ifneq ($(OPENJDK_TARGET_OS), windows) else ifeq ($(OPENJDK_TARGET_OS), macosx) LIBJSIG_CFLAGS := -m64 -D_GNU_SOURCE -pthread -mno-omit-leaf-frame-pointer -mstack-alignment=16 -fPIC LIBJSIG_LDFLAGS := $(LDFLAGS_HASH_STYLE) - # NOTE: This lib is not stripped on macosx in old build. Looks like a mistake. - LIBJSIG_STRIP_SYMBOLS := false else $(error Unknown target OS $(OPENJDK_TARGET_OS) in CompileLibjsig.gmk) endif @@ -84,20 +81,71 @@ ifneq ($(OPENJDK_TARGET_OS), windows) LIBJSIG_LDFLAGS += $(SHARED_LIBRARY_FLAGS) + LIB_OUTPUTDIR := $(call FindLibDirForModule, java.base) + $(eval $(call SetupNativeCompilation, BUILD_LIBJSIG, \ LIBRARY := jsig, \ EXTRA_FILES := $(LIBJSIG_SRC_FILE), \ - OUTPUT_DIR := $(LIBJSIG_OUTPUTDIR), \ + OUTPUT_DIR := $(LIB_OUTPUTDIR), \ LANG := C, \ CFLAGS := $(LIBJSIG_CFLAGS) $(LIBJSIG_CPU_FLAGS), \ LDFLAGS := $(LIBJSIG_LDFLAGS) $(LIBJSIG_CPU_FLAGS), \ LIBS := $(LIBJSIG_LIBS), \ MAPFILE := $(LIBJSIG_MAPFILE), \ OBJECT_DIR := $(LIBJSIG_OUTPUTDIR)/objs, \ - STRIP_SYMBOLS := $(LIBJSIG_STRIP_SYMBOLS), \ )) TARGETS += $(BUILD_LIBJSIG) + + ############################################################################ + # Create symlinks in each variant sub dir + ifeq ($(OPENJDK_TARGET_OS), macosx) + DEBUG_INFO_SUFFIX := $(SHARED_LIBRARY_SUFFIX).dSYM + else + DEBUG_INFO_SUFFIX := .debuginfo + endif + + # $1 variant subdir + define CreateSymlinks + # Always symlink from libdir/variant/libjsig.so -> ../libjsig.so and + # the corresponding debuginfo. + $(LIB_OUTPUTDIR)/$1/$(call SHARED_LIBRARY,jsig): \ + $(LIB_OUTPUTDIR)/$(call SHARED_LIBRARY,jsig) + $$(call MakeDir, $$(@D)) + $(RM) $$@ + $(LN) -s ../$$(@F) $$@ + + TARGETS += $(LIB_OUTPUTDIR)/$1/$(call SHARED_LIBRARY,jsig) + + ifeq ($(COPY_DEBUG_SYMBOLS), true) + $(LIB_OUTPUTDIR)/$1/$(LIBRARY_PREFIX)jsig$(DEBUG_INFO_SUFFIX): \ + $(LIB_OUTPUTDIR)/$(call SHARED_LIBRARY,jsig) + $$(call MakeDir, $$(@D)) + $(RM) $$@ + $(LN) -s ../$$(@F) $$@ + + TARGETS += $(LIB_OUTPUTDIR)/$1/$(LIBRARY_PREFIX)jsig$(DEBUG_INFO_SUFFIX) + + ifeq ($(ZIP_EXTERNAL_DEBUG_SYMBOLS), true) + $(LIB_OUTPUTDIR)/$1/$(LIBRARY_PREFIX)jsig.diz: \ + $(LIB_OUTPUTDIR)/$1/$(LIBRARY_PREFIX)jsig$(DEBUG_INFO_SUFFIX) + $(CD) $$(@D) && $(ZIP) -q -y $$@ $$(basename $$(@F))$(DEBUG_INFO_SUFFIX) + + TARGETS += $(LIB_OUTPUTDIR)/$1/$(LIBRARY_PREFIX)jsig.diz + endif + endif + endef + + # The subdir is the same as the variant for client and minimal, for all + # others it's server. + VARIANT_SUBDIRS := $(filter client minimal, $(JVM_VARIANTS)) \ + $(if $(filter-out client minimal, $(JVM_VARIANTS)), server) + $(foreach v, $(VARIANT_SUBDIRS), $(eval $(call CreateSymlinks,$v))) + + ############################################################################ + + include CopyToExplodedJdk.gmk + endif endif diff --git a/hotspot/make/lib/CompileLibraries.gmk b/hotspot/make/lib/CompileLibraries.gmk index d7e39e7f7b0..5224de78534 100644 --- a/hotspot/make/lib/CompileLibraries.gmk +++ b/hotspot/make/lib/CompileLibraries.gmk @@ -41,6 +41,8 @@ ifeq ($(BUILD_GTEST), true) include lib/CompileGtest.gmk endif +include CopyToExplodedJdk.gmk + all: $(TARGETS) .PHONY: all diff --git a/hotspot/make/lib/JvmOverrideFiles.gmk b/hotspot/make/lib/JvmOverrideFiles.gmk index f7827ef5c40..dabdf3b4eab 100644 --- a/hotspot/make/lib/JvmOverrideFiles.gmk +++ b/hotspot/make/lib/JvmOverrideFiles.gmk @@ -31,6 +31,7 @@ $(eval $(call IncludeCustomExtension, hotspot, lib/JvmOverrideFiles.gmk)) ifeq ($(TOOLCHAIN_TYPE), gcc) BUILD_LIBJVM_vmStructs.cpp_CXXFLAGS := -fno-var-tracking-assignments -O0 + BUILD_LIBJVM_jvmciCompilerToVM.cpp_CXXFLAGS := -fno-var-tracking-assignments endif ifeq ($(OPENJDK_TARGET_OS), linux) diff --git a/hotspot/make/test/JtregNative.gmk b/hotspot/make/test/JtregNative.gmk index 8c818122765..dc6def4fbe6 100644 --- a/hotspot/make/test/JtregNative.gmk +++ b/hotspot/make/test/JtregNative.gmk @@ -55,6 +55,9 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \ $(HOTSPOT_TOPDIR)/test/testlibrary/jvmti \ $(HOTSPOT_TOPDIR)/test/compiler/jvmci/jdk.vm.ci.code.test \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/GetModulesInfo \ + $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook \ + $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/ModuleAwareAgents/ClassLoadPrepare \ + $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/ModuleAwareAgents/ThreadStart \ # # Add conditional directories here when needed. @@ -75,6 +78,9 @@ ifeq ($(TOOLCHAIN_TYPE), solstudio) BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liboverflow := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libSimpleClassFileLoadHook := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libGetNamedModuleTest := -lc + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAClassFileLoadHook := -lc + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAClassLoadPrepare := -lc + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAThreadStart := -lc endif ifeq ($(OPENJDK_TARGET_OS), linux) diff --git a/hotspot/src/cpu/aarch64/vm/c1_LIRGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_LIRGenerator_aarch64.cpp index e66f6ff5fe5..033741723e8 100644 --- a/hotspot/src/cpu/aarch64/vm/c1_LIRGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/c1_LIRGenerator_aarch64.cpp @@ -140,10 +140,11 @@ LIR_Opr LIRGenerator::safepoint_poll_register() { LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index, int shift, int disp, BasicType type) { assert(base->is_register(), "must be"); + intx large_disp = disp; // accumulate fixed displacements if (index->is_constant()) { - disp += index->as_constant_ptr()->as_jint() << shift; + large_disp += (intx)(index->as_constant_ptr()->as_jint()) << shift; index = LIR_OprFact::illegalOpr; } @@ -154,31 +155,31 @@ LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index, __ shift_left(index, shift, tmp); index = tmp; } - if (disp != 0) { + if (large_disp != 0) { LIR_Opr tmp = new_pointer_register(); - if (Assembler::operand_valid_for_add_sub_immediate(disp)) { - __ add(tmp, tmp, LIR_OprFact::intptrConst(disp)); + if (Assembler::operand_valid_for_add_sub_immediate(large_disp)) { + __ add(tmp, tmp, LIR_OprFact::intptrConst(large_disp)); index = tmp; } else { - __ move(tmp, LIR_OprFact::intptrConst(disp)); + __ move(tmp, LIR_OprFact::intptrConst(large_disp)); __ add(tmp, index, tmp); index = tmp; } - disp = 0; + large_disp = 0; } - } else if (disp != 0 && !Address::offset_ok_for_immed(disp, shift)) { + } else if (large_disp != 0 && !Address::offset_ok_for_immed(large_disp, shift)) { // index is illegal so replace it with the displacement loaded into a register index = new_pointer_register(); - __ move(LIR_OprFact::intptrConst(disp), index); - disp = 0; + __ move(LIR_OprFact::intptrConst(large_disp), index); + large_disp = 0; } // at this point we either have base + index or base + displacement - if (disp == 0) { + if (large_disp == 0) { return new LIR_Address(base, index, type); } else { - assert(Address::offset_ok_for_immed(disp, 0), "must be"); - return new LIR_Address(base, disp, type); + assert(Address::offset_ok_for_immed(large_disp, 0), "must be"); + return new LIR_Address(base, large_disp, type); } } @@ -192,7 +193,7 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o LIR_Address* addr; if (index_opr->is_constant()) { addr = new LIR_Address(array_opr, - offset_in_bytes + index_opr->as_jint() * elem_size, type); + offset_in_bytes + (intx)(index_opr->as_jint()) * elem_size, type); } else { if (offset_in_bytes) { LIR_Opr tmp = new_pointer_register(); @@ -1032,6 +1033,10 @@ void LIRGenerator::do_update_CRC32C(Intrinsic* x) { Unimplemented(); } +void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { + fatal("FMA intrinsic is not implemented on this platform"); +} + void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { fatal("vectorizedMismatch intrinsic is not implemented on this platform"); } diff --git a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp index 91e32e94afa..76e0cbeabf8 100644 --- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp @@ -327,7 +327,7 @@ void InterpreterMacroAssembler::push_i(Register r) { void InterpreterMacroAssembler::push_l(Register r) { str(zr, pre(esp, -wordSize)); - str(r, pre(esp, -wordsize)); + str(r, pre(esp, - wordSize)); } void InterpreterMacroAssembler::pop_f(FloatRegister r) { diff --git a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp index f1470162e61..53a294b8601 100644 --- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp @@ -262,6 +262,11 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); } + if (UseFMA) { + warning("FMA instructions are not available on this CPU"); + FLAG_SET_DEFAULT(UseFMA, false); + } + if (auxv & (HWCAP_SHA1 | HWCAP_SHA2)) { if (FLAG_IS_DEFAULT(UseSHA)) { FLAG_SET_DEFAULT(UseSHA, true); diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp index e81d08e848a..9c684e4aca2 100644 --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp @@ -506,6 +506,8 @@ class Assembler : public AbstractAssembler { // Vector-Scalar (VSX) instruction support. LXVD2X_OPCODE = (31u << OPCODE_SHIFT | 844u << 1), STXVD2X_OPCODE = (31u << OPCODE_SHIFT | 972u << 1), + MTVSRD_OPCODE = (31u << OPCODE_SHIFT | 179u << 1), + MFVSRD_OPCODE = (31u << OPCODE_SHIFT | 51u << 1), // Vector Permute and Formatting VPKPX_OPCODE = (4u << OPCODE_SHIFT | 782u ), @@ -1573,6 +1575,9 @@ class Assembler : public AbstractAssembler { inline void stdu( Register d, int si16, Register s1); inline void stdux(Register s, Register a, Register b); + inline void st_ptr(Register d, int si16, Register s1); + DEBUG_ONLY(inline void st_ptr(Register d, ByteSize b, Register s1);) + // PPC 1, section 3.3.13 Move To/From System Register Instructions inline void mtlr( Register s1); inline void mflr( Register d); @@ -2099,6 +2104,8 @@ class Assembler : public AbstractAssembler { // Vector-Scalar (VSX) instructions. inline void lxvd2x( VectorSRegister d, Register a, Register b); inline void stxvd2x( VectorSRegister d, Register a, Register b); + inline void mtvrd( VectorRegister d, Register a); + inline void mfvrd( Register a, VectorRegister d); // AES (introduced with Power 8) inline void vcipher( VectorRegister d, VectorRegister a, VectorRegister b); diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp index 14f25e4eea8..f46f47dc311 100644 --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp @@ -349,6 +349,9 @@ inline void Assembler::stdx( Register d, Register s1, Register s2) { emit_int32( inline void Assembler::stdu( Register d, int si16, Register s1) { emit_int32(STDU_OPCODE | rs(d) | ds(si16) | rta0mem(s1));} inline void Assembler::stdux(Register s, Register a, Register b) { emit_int32(STDUX_OPCODE| rs(s) | rta0mem(a) | rb(b));} +inline void Assembler::st_ptr(Register d, int b, Register s1) { std(d, b, s1); } +DEBUG_ONLY(inline void Assembler::st_ptr(Register d, ByteSize b, Register s1) { std(d, in_bytes(b), s1); }) + // PPC 1, section 3.3.13 Move To/From System Register Instructions inline void Assembler::mtlr( Register s1) { emit_int32(MTLR_OPCODE | rs(s1)); } inline void Assembler::mflr( Register d ) { emit_int32(MFLR_OPCODE | rt(d)); } @@ -733,6 +736,8 @@ inline void Assembler::lvsr( VectorRegister d, Register s1, Register s2) { emit // Vector-Scalar (VSX) instructions. inline void Assembler::lxvd2x (VectorSRegister d, Register s1, Register s2) { emit_int32( LXVD2X_OPCODE | vsrt(d) | ra(s1) | rb(s2)); } inline void Assembler::stxvd2x(VectorSRegister d, Register s1, Register s2) { emit_int32( STXVD2X_OPCODE | vsrt(d) | ra(s1) | rb(s2)); } +inline void Assembler::mtvrd( VectorRegister d, Register a) { emit_int32( MTVSRD_OPCODE | vrt(d) | ra(a) | 1u); } // 1u: d is treated as Vector (VMX/Altivec). +inline void Assembler::mfvrd( Register a, VectorRegister d) { emit_int32( MFVSRD_OPCODE | vrt(d) | ra(a) | 1u); } // 1u: d is treated as Vector (VMX/Altivec). inline void Assembler::vpkpx( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKPX_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vpkshss( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKSHSS_OPCODE | vrt(d) | vra(a) | vrb(b)); } diff --git a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp index c8ebff099f9..2cb7fe73e79 100644 --- a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp @@ -157,10 +157,11 @@ LIR_Opr LIRGenerator::safepoint_poll_register() { LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index, int shift, int disp, BasicType type) { assert(base->is_register(), "must be"); + intx large_disp = disp; // Accumulate fixed displacements. if (index->is_constant()) { - disp += index->as_constant_ptr()->as_jint() << shift; + large_disp += (intx)(index->as_constant_ptr()->as_jint()) << shift; index = LIR_OprFact::illegalOpr; } @@ -171,31 +172,31 @@ LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index, __ shift_left(index, shift, tmp); index = tmp; } - if (disp != 0) { + if (large_disp != 0) { LIR_Opr tmp = new_pointer_register(); - if (Assembler::is_simm16(disp)) { - __ add(index, LIR_OprFact::intptrConst(disp), tmp); + if (Assembler::is_simm16(large_disp)) { + __ add(index, LIR_OprFact::intptrConst(large_disp), tmp); index = tmp; } else { - __ move(LIR_OprFact::intptrConst(disp), tmp); + __ move(LIR_OprFact::intptrConst(large_disp), tmp); __ add(tmp, index, tmp); index = tmp; } - disp = 0; + large_disp = 0; } - } else if (!Assembler::is_simm16(disp)) { + } else if (!Assembler::is_simm16(large_disp)) { // Index is illegal so replace it with the displacement loaded into a register. index = new_pointer_register(); - __ move(LIR_OprFact::intptrConst(disp), index); - disp = 0; + __ move(LIR_OprFact::intptrConst(large_disp), index); + large_disp = 0; } // At this point we either have base + index or base + displacement. - if (disp == 0) { + if (large_disp == 0) { return new LIR_Address(base, index, type); } else { - assert(Assembler::is_simm16(disp), "must be"); - return new LIR_Address(base, disp, type); + assert(Assembler::is_simm16(large_disp), "must be"); + return new LIR_Address(base, large_disp, type); } } @@ -206,11 +207,11 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o int shift = exact_log2(elem_size); LIR_Opr base_opr; - int offset = arrayOopDesc::base_offset_in_bytes(type); + intx offset = arrayOopDesc::base_offset_in_bytes(type); if (index_opr->is_constant()) { - int i = index_opr->as_constant_ptr()->as_jint(); - int array_offset = i * elem_size; + intx i = index_opr->as_constant_ptr()->as_jint(); + intx array_offset = i * elem_size; if (Assembler::is_simm16(array_offset + offset)) { base_opr = array_opr; offset = array_offset + offset; @@ -1433,6 +1434,10 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { } } +void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { + fatal("FMA intrinsic is not implemented on this platform"); +} + void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { fatal("vectorizedMismatch intrinsic is not implemented on this platform"); } diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp index 70544e9366a..95234115319 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp @@ -261,6 +261,9 @@ void InterpreterMacroAssembler::push_ptr(Register r) { } void InterpreterMacroAssembler::push_l(Register r) { + // Clear unused slot. + load_const_optimized(R0, 0L); + std(R0, 0, R15_esp); std(r, - Interpreter::stackElementSize, R15_esp); addi(R15_esp, R15_esp, - 2 * Interpreter::stackElementSize ); } diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index 5d58dab4995..417e6a3a27a 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -4332,6 +4332,565 @@ void MacroAssembler::kernel_crc32_1byte(Register crc, Register buf, Register len BLOCK_COMMENT("} kernel_crc32_1byte"); } +/** + * @param crc register containing existing CRC (32-bit) + * @param buf register pointing to input byte buffer (byte*) + * @param len register containing number of bytes + * @param table register pointing to CRC table + * @param constants register pointing to CRC table for 128-bit aligned memory + * @param barretConstants register pointing to table for barrett reduction + * @param t0 volatile register + * @param t1 volatile register + * @param t2 volatile register + * @param t3 volatile register + */ +void MacroAssembler::kernel_crc32_1word_vpmsumd(Register crc, Register buf, Register len, Register table, + Register constants, Register barretConstants, + Register t0, Register t1, Register t2, Register t3, Register t4) { + assert_different_registers(crc, buf, len, table); + + Label L_alignedHead, L_tail, L_alignTail, L_start, L_end; + + Register prealign = t0; + Register postalign = t0; + + BLOCK_COMMENT("kernel_crc32_1word_vpmsumb {"); + + // 1. use kernel_crc32_1word for shorter than 384bit + clrldi(len, len, 32); + cmpdi(CCR0, len, 384); + bge(CCR0, L_start); + + Register tc0 = t4; + Register tc1 = constants; + Register tc2 = barretConstants; + kernel_crc32_1word(crc, buf, len, table,t0, t1, t2, t3, tc0, tc1, tc2, table); + b(L_end); + + BIND(L_start); + + // 2. ~c + nand(crc, crc, crc); + + // 3. calculate from 0 to first 128bit-aligned address + clrldi_(prealign, buf, 57); + beq(CCR0, L_alignedHead); + + subfic(prealign, prealign, 128); + + subf(len, prealign, len); + update_byteLoop_crc32(crc, buf, prealign, table, t2, false, false); + + // 4. calculate from first 128bit-aligned address to last 128bit-aligned address + BIND(L_alignedHead); + + clrldi(postalign, len, 57); + subf(len, postalign, len); + + // len must be more than 256bit + kernel_crc32_1word_aligned(crc, buf, len, constants, barretConstants, t1, t2, t3); + + // 5. calculate remaining + cmpdi(CCR0, postalign, 0); + beq(CCR0, L_tail); + + update_byteLoop_crc32(crc, buf, postalign, table, t2, false, false); + + BIND(L_tail); + + // 6. ~c + nand(crc, crc, crc); + + BIND(L_end); + + BLOCK_COMMENT("} kernel_crc32_1word_vpmsumb"); +} + +/** + * @param crc register containing existing CRC (32-bit) + * @param buf register pointing to input byte buffer (byte*) + * @param len register containing number of bytes + * @param constants register pointing to CRC table for 128-bit aligned memory + * @param barretConstants register pointing to table for barrett reduction + * @param t0 volatile register + * @param t1 volatile register + * @param t2 volatile register + */ +void MacroAssembler::kernel_crc32_1word_aligned(Register crc, Register buf, Register len, + Register constants, Register barretConstants, Register t0, Register t1, Register t2) { + Label L_mainLoop, L_tail, L_alignTail, L_barrett_reduction, L_end, L_first_warm_up_done, L_first_cool_down, L_second_cool_down, L_XOR, L_test; + Label L_lv0, L_lv1, L_lv2, L_lv3, L_lv4, L_lv5, L_lv6, L_lv7, L_lv8, L_lv9, L_lv10, L_lv11, L_lv12, L_lv13, L_lv14, L_lv15; + Label L_1, L_2, L_3, L_4; + + Register rLoaded = t0; + Register rTmp1 = t1; + Register rTmp2 = t2; + Register off16 = R22; + Register off32 = R23; + Register off48 = R24; + Register off64 = R25; + Register off80 = R26; + Register off96 = R27; + Register off112 = R28; + Register rIdx = R29; + Register rMax = R30; + Register constantsPos = R31; + + VectorRegister mask_32bit = VR24; + VectorRegister mask_64bit = VR25; + VectorRegister zeroes = VR26; + VectorRegister const1 = VR27; + VectorRegister const2 = VR28; + + // Save non-volatile vector registers (frameless). + Register offset = t1; int offsetInt = 0; + offsetInt -= 16; li(offset, -16); stvx(VR20, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); stvx(VR21, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); stvx(VR22, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); stvx(VR23, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); stvx(VR24, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); stvx(VR25, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); stvx(VR26, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); stvx(VR27, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); stvx(VR28, offset, R1_SP); + offsetInt -= 8; std(R22, offsetInt, R1_SP); + offsetInt -= 8; std(R23, offsetInt, R1_SP); + offsetInt -= 8; std(R24, offsetInt, R1_SP); + offsetInt -= 8; std(R25, offsetInt, R1_SP); + offsetInt -= 8; std(R26, offsetInt, R1_SP); + offsetInt -= 8; std(R27, offsetInt, R1_SP); + offsetInt -= 8; std(R28, offsetInt, R1_SP); + offsetInt -= 8; std(R29, offsetInt, R1_SP); + offsetInt -= 8; std(R30, offsetInt, R1_SP); + offsetInt -= 8; std(R31, offsetInt, R1_SP); + + // Set constants + li(off16, 16); + li(off32, 32); + li(off48, 48); + li(off64, 64); + li(off80, 80); + li(off96, 96); + li(off112, 112); + + clrldi(crc, crc, 32); + + vxor(zeroes, zeroes, zeroes); + vspltisw(VR0, -1); + + vsldoi(mask_32bit, zeroes, VR0, 4); + vsldoi(mask_64bit, zeroes, VR0, -8); + + // Get the initial value into v8 + vxor(VR8, VR8, VR8); + mtvrd(VR8, crc); + vsldoi(VR8, zeroes, VR8, -8); // shift into bottom 32 bits + + li (rLoaded, 0); + + rldicr(rIdx, len, 0, 56); + + { + BIND(L_1); + // Checksum in blocks of MAX_SIZE (32768) + lis(rMax, 0); + ori(rMax, rMax, 32768); + mr(rTmp2, rMax); + cmpd(CCR0, rIdx, rMax); + bgt(CCR0, L_2); + mr(rMax, rIdx); + + BIND(L_2); + subf(rIdx, rMax, rIdx); + + // our main loop does 128 bytes at a time + srdi(rMax, rMax, 7); + + /* + * Work out the offset into the constants table to start at. Each + * constant is 16 bytes, and it is used against 128 bytes of input + * data - 128 / 16 = 8 + */ + sldi(rTmp1, rMax, 4); + srdi(rTmp2, rTmp2, 3); + subf(rTmp1, rTmp1, rTmp2); + + // We reduce our final 128 bytes in a separate step + addi(rMax, rMax, -1); + mtctr(rMax); + + // Find the start of our constants + add(constantsPos, constants, rTmp1); + + // zero VR0-v7 which will contain our checksums + vxor(VR0, VR0, VR0); + vxor(VR1, VR1, VR1); + vxor(VR2, VR2, VR2); + vxor(VR3, VR3, VR3); + vxor(VR4, VR4, VR4); + vxor(VR5, VR5, VR5); + vxor(VR6, VR6, VR6); + vxor(VR7, VR7, VR7); + + lvx(const1, constantsPos); + + /* + * If we are looping back to consume more data we use the values + * already in VR16-v23. + */ + cmpdi(CCR0, rLoaded, 1); + beq(CCR0, L_3); + { + + // First warm up pass + lvx(VR16, buf); + lvx(VR17, off16, buf); + lvx(VR18, off32, buf); + lvx(VR19, off48, buf); + lvx(VR20, off64, buf); + lvx(VR21, off80, buf); + lvx(VR22, off96, buf); + lvx(VR23, off112, buf); + addi(buf, buf, 8*16); + + // xor in initial value + vxor(VR16, VR16, VR8); + } + + BIND(L_3); + bdz(L_first_warm_up_done); + + addi(constantsPos, constantsPos, 16); + lvx(const2, constantsPos); + + // Second warm up pass + vpmsumd(VR8, VR16, const1); + lvx(VR16, buf); + + vpmsumd(VR9, VR17, const1); + lvx(VR17, off16, buf); + + vpmsumd(VR10, VR18, const1); + lvx(VR18, off32, buf); + + vpmsumd(VR11, VR19, const1); + lvx(VR19, off48, buf); + + vpmsumd(VR12, VR20, const1); + lvx(VR20, off64, buf); + + vpmsumd(VR13, VR21, const1); + lvx(VR21, off80, buf); + + vpmsumd(VR14, VR22, const1); + lvx(VR22, off96, buf); + + vpmsumd(VR15, VR23, const1); + lvx(VR23, off112, buf); + + addi(buf, buf, 8 * 16); + + bdz(L_first_cool_down); + + /* + * main loop. We modulo schedule it such that it takes three iterations + * to complete - first iteration load, second iteration vpmsum, third + * iteration xor. + */ + { + BIND(L_4); + lvx(const1, constantsPos); addi(constantsPos, constantsPos, 16); + + vxor(VR0, VR0, VR8); + vpmsumd(VR8, VR16, const2); + lvx(VR16, buf); + + vxor(VR1, VR1, VR9); + vpmsumd(VR9, VR17, const2); + lvx(VR17, off16, buf); + + vxor(VR2, VR2, VR10); + vpmsumd(VR10, VR18, const2); + lvx(VR18, off32, buf); + + vxor(VR3, VR3, VR11); + vpmsumd(VR11, VR19, const2); + lvx(VR19, off48, buf); + lvx(const2, constantsPos); + + vxor(VR4, VR4, VR12); + vpmsumd(VR12, VR20, const1); + lvx(VR20, off64, buf); + + vxor(VR5, VR5, VR13); + vpmsumd(VR13, VR21, const1); + lvx(VR21, off80, buf); + + vxor(VR6, VR6, VR14); + vpmsumd(VR14, VR22, const1); + lvx(VR22, off96, buf); + + vxor(VR7, VR7, VR15); + vpmsumd(VR15, VR23, const1); + lvx(VR23, off112, buf); + + addi(buf, buf, 8 * 16); + + bdnz(L_4); + } + + BIND(L_first_cool_down); + + // First cool down pass + lvx(const1, constantsPos); + addi(constantsPos, constantsPos, 16); + + vxor(VR0, VR0, VR8); + vpmsumd(VR8, VR16, const1); + + vxor(VR1, VR1, VR9); + vpmsumd(VR9, VR17, const1); + + vxor(VR2, VR2, VR10); + vpmsumd(VR10, VR18, const1); + + vxor(VR3, VR3, VR11); + vpmsumd(VR11, VR19, const1); + + vxor(VR4, VR4, VR12); + vpmsumd(VR12, VR20, const1); + + vxor(VR5, VR5, VR13); + vpmsumd(VR13, VR21, const1); + + vxor(VR6, VR6, VR14); + vpmsumd(VR14, VR22, const1); + + vxor(VR7, VR7, VR15); + vpmsumd(VR15, VR23, const1); + + BIND(L_second_cool_down); + // Second cool down pass + vxor(VR0, VR0, VR8); + vxor(VR1, VR1, VR9); + vxor(VR2, VR2, VR10); + vxor(VR3, VR3, VR11); + vxor(VR4, VR4, VR12); + vxor(VR5, VR5, VR13); + vxor(VR6, VR6, VR14); + vxor(VR7, VR7, VR15); + + /* + * vpmsumd produces a 96 bit result in the least significant bits + * of the register. Since we are bit reflected we have to shift it + * left 32 bits so it occupies the least significant bits in the + * bit reflected domain. + */ + vsldoi(VR0, VR0, zeroes, 4); + vsldoi(VR1, VR1, zeroes, 4); + vsldoi(VR2, VR2, zeroes, 4); + vsldoi(VR3, VR3, zeroes, 4); + vsldoi(VR4, VR4, zeroes, 4); + vsldoi(VR5, VR5, zeroes, 4); + vsldoi(VR6, VR6, zeroes, 4); + vsldoi(VR7, VR7, zeroes, 4); + + // xor with last 1024 bits + lvx(VR8, buf); + lvx(VR9, off16, buf); + lvx(VR10, off32, buf); + lvx(VR11, off48, buf); + lvx(VR12, off64, buf); + lvx(VR13, off80, buf); + lvx(VR14, off96, buf); + lvx(VR15, off112, buf); + addi(buf, buf, 8 * 16); + + vxor(VR16, VR0, VR8); + vxor(VR17, VR1, VR9); + vxor(VR18, VR2, VR10); + vxor(VR19, VR3, VR11); + vxor(VR20, VR4, VR12); + vxor(VR21, VR5, VR13); + vxor(VR22, VR6, VR14); + vxor(VR23, VR7, VR15); + + li(rLoaded, 1); + cmpdi(CCR0, rIdx, 0); + addi(rIdx, rIdx, 128); + bne(CCR0, L_1); + } + + // Work out how many bytes we have left + andi_(len, len, 127); + + // Calculate where in the constant table we need to start + subfic(rTmp1, len, 128); + add(constantsPos, constantsPos, rTmp1); + + // How many 16 byte chunks are in the tail + srdi(rIdx, len, 4); + mtctr(rIdx); + + /* + * Reduce the previously calculated 1024 bits to 64 bits, shifting + * 32 bits to include the trailing 32 bits of zeros + */ + lvx(VR0, constantsPos); + lvx(VR1, off16, constantsPos); + lvx(VR2, off32, constantsPos); + lvx(VR3, off48, constantsPos); + lvx(VR4, off64, constantsPos); + lvx(VR5, off80, constantsPos); + lvx(VR6, off96, constantsPos); + lvx(VR7, off112, constantsPos); + addi(constantsPos, constantsPos, 8 * 16); + + vpmsumw(VR0, VR16, VR0); + vpmsumw(VR1, VR17, VR1); + vpmsumw(VR2, VR18, VR2); + vpmsumw(VR3, VR19, VR3); + vpmsumw(VR4, VR20, VR4); + vpmsumw(VR5, VR21, VR5); + vpmsumw(VR6, VR22, VR6); + vpmsumw(VR7, VR23, VR7); + + // Now reduce the tail (0 - 112 bytes) + cmpdi(CCR0, rIdx, 0); + beq(CCR0, L_XOR); + + lvx(VR16, buf); addi(buf, buf, 16); + lvx(VR17, constantsPos); + vpmsumw(VR16, VR16, VR17); + vxor(VR0, VR0, VR16); + beq(CCR0, L_XOR); + + lvx(VR16, buf); addi(buf, buf, 16); + lvx(VR17, off16, constantsPos); + vpmsumw(VR16, VR16, VR17); + vxor(VR0, VR0, VR16); + beq(CCR0, L_XOR); + + lvx(VR16, buf); addi(buf, buf, 16); + lvx(VR17, off32, constantsPos); + vpmsumw(VR16, VR16, VR17); + vxor(VR0, VR0, VR16); + beq(CCR0, L_XOR); + + lvx(VR16, buf); addi(buf, buf, 16); + lvx(VR17, off48,constantsPos); + vpmsumw(VR16, VR16, VR17); + vxor(VR0, VR0, VR16); + beq(CCR0, L_XOR); + + lvx(VR16, buf); addi(buf, buf, 16); + lvx(VR17, off64, constantsPos); + vpmsumw(VR16, VR16, VR17); + vxor(VR0, VR0, VR16); + beq(CCR0, L_XOR); + + lvx(VR16, buf); addi(buf, buf, 16); + lvx(VR17, off80, constantsPos); + vpmsumw(VR16, VR16, VR17); + vxor(VR0, VR0, VR16); + beq(CCR0, L_XOR); + + lvx(VR16, buf); addi(buf, buf, 16); + lvx(VR17, off96, constantsPos); + vpmsumw(VR16, VR16, VR17); + vxor(VR0, VR0, VR16); + + // Now xor all the parallel chunks together + BIND(L_XOR); + vxor(VR0, VR0, VR1); + vxor(VR2, VR2, VR3); + vxor(VR4, VR4, VR5); + vxor(VR6, VR6, VR7); + + vxor(VR0, VR0, VR2); + vxor(VR4, VR4, VR6); + + vxor(VR0, VR0, VR4); + + b(L_barrett_reduction); + + BIND(L_first_warm_up_done); + lvx(const1, constantsPos); + addi(constantsPos, constantsPos, 16); + vpmsumd(VR8, VR16, const1); + vpmsumd(VR9, VR17, const1); + vpmsumd(VR10, VR18, const1); + vpmsumd(VR11, VR19, const1); + vpmsumd(VR12, VR20, const1); + vpmsumd(VR13, VR21, const1); + vpmsumd(VR14, VR22, const1); + vpmsumd(VR15, VR23, const1); + b(L_second_cool_down); + + BIND(L_barrett_reduction); + + lvx(const1, barretConstants); + addi(barretConstants, barretConstants, 16); + lvx(const2, barretConstants); + + vsldoi(VR1, VR0, VR0, -8); + vxor(VR0, VR0, VR1); // xor two 64 bit results together + + // shift left one bit + vspltisb(VR1, 1); + vsl(VR0, VR0, VR1); + + vand(VR0, VR0, mask_64bit); + + /* + * The reflected version of Barrett reduction. Instead of bit + * reflecting our data (which is expensive to do), we bit reflect our + * constants and our algorithm, which means the intermediate data in + * our vector registers goes from 0-63 instead of 63-0. We can reflect + * the algorithm because we don't carry in mod 2 arithmetic. + */ + vand(VR1, VR0, mask_32bit); // bottom 32 bits of a + vpmsumd(VR1, VR1, const1); // ma + vand(VR1, VR1, mask_32bit); // bottom 32bits of ma + vpmsumd(VR1, VR1, const2); // qn */ + vxor(VR0, VR0, VR1); // a - qn, subtraction is xor in GF(2) + + /* + * Since we are bit reflected, the result (ie the low 32 bits) is in + * the high 32 bits. We just need to shift it left 4 bytes + * V0 [ 0 1 X 3 ] + * V0 [ 0 X 2 3 ] + */ + vsldoi(VR0, VR0, zeroes, 4); // shift result into top 64 bits of + + // Get it into r3 + mfvrd(crc, VR0); + + BIND(L_end); + + offsetInt = 0; + // Restore non-volatile Vector registers (frameless). + offsetInt -= 16; li(offset, -16); lvx(VR20, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); lvx(VR21, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); lvx(VR22, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); lvx(VR23, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); lvx(VR24, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); lvx(VR25, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); lvx(VR26, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); lvx(VR27, offset, R1_SP); + offsetInt -= 16; addi(offset, offset, -16); lvx(VR28, offset, R1_SP); + offsetInt -= 8; ld(R22, offsetInt, R1_SP); + offsetInt -= 8; ld(R23, offsetInt, R1_SP); + offsetInt -= 8; ld(R24, offsetInt, R1_SP); + offsetInt -= 8; ld(R25, offsetInt, R1_SP); + offsetInt -= 8; ld(R26, offsetInt, R1_SP); + offsetInt -= 8; ld(R27, offsetInt, R1_SP); + offsetInt -= 8; ld(R28, offsetInt, R1_SP); + offsetInt -= 8; ld(R29, offsetInt, R1_SP); + offsetInt -= 8; ld(R30, offsetInt, R1_SP); + offsetInt -= 8; ld(R31, offsetInt, R1_SP); +} + void MacroAssembler::kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp) { assert_different_registers(crc, buf, /* len, not used!! */ table, tmp); diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp index ed846efb580..3e481d84cf9 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp @@ -834,6 +834,13 @@ class MacroAssembler: public Assembler { Register tc0, Register tc1, Register tc2, Register tc3); void kernel_crc32_1byte(Register crc, Register buf, Register len, Register table, Register t0, Register t1, Register t2, Register t3); + void kernel_crc32_1word_vpmsumd(Register crc, Register buf, Register len, Register table, + Register constants, Register barretConstants, + Register t0, Register t1, Register t2, Register t3, Register t4); + void kernel_crc32_1word_aligned(Register crc, Register buf, Register len, + Register constants, Register barretConstants, + Register t0, Register t1, Register t2); + void kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp); // diff --git a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp index 609420a675b..5044e80a0a9 100644 --- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp @@ -2489,6 +2489,11 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, __ verify_oop(R3_RET); } + if (CheckJNICalls) { + // clear_pending_jni_exception_check + __ load_const_optimized(R0, 0L); + __ st_ptr(R0, JavaThread::pending_jni_exception_check_fn_offset(), R16_thread); + } // Reset handle block. // -------------------------------------------------------------------------- diff --git a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp index cf07f2bd5dc..e638c5a6773 100644 --- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp @@ -3205,28 +3205,59 @@ class StubGenerator: public StubCodeGenerator { const Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call. const Register data = R4_ARG2; // source byte array const Register dataLen = R5_ARG3; // #bytes to process - const Register table = R6_ARG4; // crc table address - const Register t0 = R2; - const Register t1 = R7; - const Register t2 = R8; - const Register t3 = R9; - const Register tc0 = R10; - const Register tc1 = R11; - const Register tc2 = R12; + const Register table = R6; // crc table address - BLOCK_COMMENT("Stub body {"); - assert_different_registers(crc, data, dataLen, table); +#ifdef VM_LITTLE_ENDIAN + if (VM_Version::has_vpmsumb()) { + const Register constants = R2; // constants address + const Register bconstants = R8; // barret table address - StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table); + const Register t0 = R9; + const Register t1 = R10; + const Register t2 = R11; + const Register t3 = R12; + const Register t4 = R7; - __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, table); + BLOCK_COMMENT("Stub body {"); + assert_different_registers(crc, data, dataLen, table); - BLOCK_COMMENT("return"); - __ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET). - __ blr(); + StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table); + StubRoutines::ppc64::generate_load_crc_constants_addr(_masm, constants); + StubRoutines::ppc64::generate_load_crc_barret_constants_addr(_masm, bconstants); + + __ kernel_crc32_1word_vpmsumd(crc, data, dataLen, table, constants, bconstants, t0, t1, t2, t3, t4); + + BLOCK_COMMENT("return"); + __ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET). + __ blr(); + + BLOCK_COMMENT("} Stub body"); + } else +#endif + { + const Register t0 = R2; + const Register t1 = R7; + const Register t2 = R8; + const Register t3 = R9; + const Register tc0 = R10; + const Register tc1 = R11; + const Register tc2 = R12; + + BLOCK_COMMENT("Stub body {"); + assert_different_registers(crc, data, dataLen, table); + + StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table); + + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, table); + + BLOCK_COMMENT("return"); + __ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET). + __ blr(); + + BLOCK_COMMENT("} Stub body"); + } - BLOCK_COMMENT("} Stub body"); return start; } diff --git a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc.hpp b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc.hpp index b04c99cf64e..5b5b2c270dd 100644 --- a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc.hpp @@ -45,6 +45,8 @@ enum platform_dependent_constants { #else #define CRC32_TABLES 1 #endif +#define CRC32_CONSTANTS_SIZE 1084 +#define CRC32_BARRET_CONSTANTS 10 class ppc64 { friend class StubGenerator; @@ -53,11 +55,17 @@ class ppc64 { // CRC32 Intrinsics. static juint _crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE]; + static juint* _constants; + static juint* _barret_constants; public: // CRC32 Intrinsics. static void generate_load_crc_table_addr(MacroAssembler* masm, Register table); + static void generate_load_crc_constants_addr(MacroAssembler* masm, Register table); + static void generate_load_crc_barret_constants_addr(MacroAssembler* masm, Register table); + static juint* generate_crc_constants(); + static juint* generate_crc_barret_constants(); }; diff --git a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp index bed7f40a501..088d63a2f79 100644 --- a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp @@ -37,6 +37,311 @@ void StubRoutines::ppc64::generate_load_crc_table_addr(MacroAssembler* masm, Reg __ load_const_optimized(table, StubRoutines::_crc_table_adr, R0); } +void StubRoutines::ppc64::generate_load_crc_constants_addr(MacroAssembler* masm, Register table) { + __ load_const_optimized(table, (address)StubRoutines::ppc64::_constants, R0); +} + +void StubRoutines::ppc64::generate_load_crc_barret_constants_addr(MacroAssembler* masm, Register table) { + __ load_const_optimized(table, (address)StubRoutines::ppc64::_barret_constants, R0); +} + +juint* StubRoutines::ppc64::generate_crc_constants() { + juint constants[CRC32_CONSTANTS_SIZE] = { + // Reduce 262144 kbits to 1024 bits + 0x99ea94a8UL, 0x00000000UL, 0x651797d2UL, 0x00000001UL, // x^261120 mod p(x)` << 1, x^261184 mod p(x)` << 1 + 0x945a8420UL, 0x00000000UL, 0x21e0d56cUL, 0x00000000UL, // x^260096 mod p(x)` << 1, x^260160 mod p(x)` << 1 + 0x30762706UL, 0x00000000UL, 0x0f95ecaaUL, 0x00000000UL, // x^259072 mod p(x)` << 1, x^259136 mod p(x)` << 1 + 0xa52fc582UL, 0x00000001UL, 0xebd224acUL, 0x00000001UL, // x^258048 mod p(x)` << 1, x^258112 mod p(x)` << 1 + 0xa4a7167aUL, 0x00000001UL, 0x0ccb97caUL, 0x00000000UL, // x^257024 mod p(x)` << 1, x^257088 mod p(x)` << 1 + 0x0c18249aUL, 0x00000000UL, 0x006ec8a8UL, 0x00000001UL, // x^256000 mod p(x)` << 1, x^256064 mod p(x)` << 1 + 0xa924ae7cUL, 0x00000000UL, 0x4f58f196UL, 0x00000001UL, // x^254976 mod p(x)` << 1, x^255040 mod p(x)` << 1 + 0xe12ccc12UL, 0x00000001UL, 0xa7192ca6UL, 0x00000001UL, // x^253952 mod p(x)` << 1, x^254016 mod p(x)` << 1 + 0xa0b9d4acUL, 0x00000000UL, 0x9a64bab2UL, 0x00000001UL, // x^252928 mod p(x)` << 1, x^252992 mod p(x)` << 1 + 0x95e8ddfeUL, 0x00000000UL, 0x14f4ed2eUL, 0x00000000UL, // x^251904 mod p(x)` << 1, x^251968 mod p(x)` << 1 + 0x233fddc4UL, 0x00000000UL, 0x1092b6a2UL, 0x00000001UL, // x^250880 mod p(x)` << 1, x^250944 mod p(x)` << 1 + 0xb4529b62UL, 0x00000001UL, 0xc8a1629cUL, 0x00000000UL, // x^249856 mod p(x)` << 1, x^249920 mod p(x)` << 1 + 0xa7fa0e64UL, 0x00000001UL, 0x7bf32e8eUL, 0x00000001UL, // x^248832 mod p(x)` << 1, x^248896 mod p(x)` << 1 + 0xb5334592UL, 0x00000001UL, 0xf8cc6582UL, 0x00000001UL, // x^247808 mod p(x)` << 1, x^247872 mod p(x)` << 1 + 0x1f8ee1b4UL, 0x00000001UL, 0x8631ddf0UL, 0x00000000UL, // x^246784 mod p(x)` << 1, x^246848 mod p(x)` << 1 + 0x6252e632UL, 0x00000000UL, 0x7e5a76d0UL, 0x00000000UL, // x^245760 mod p(x)` << 1, x^245824 mod p(x)` << 1 + 0xab973e84UL, 0x00000000UL, 0x2b09b31cUL, 0x00000000UL, // x^244736 mod p(x)` << 1, x^244800 mod p(x)` << 1 + 0x7734f5ecUL, 0x00000000UL, 0xb2df1f84UL, 0x00000001UL, // x^243712 mod p(x)` << 1, x^243776 mod p(x)` << 1 + 0x7c547798UL, 0x00000000UL, 0xd6f56afcUL, 0x00000001UL, // x^242688 mod p(x)` << 1, x^242752 mod p(x)` << 1 + 0x7ec40210UL, 0x00000000UL, 0xb9b5e70cUL, 0x00000001UL, // x^241664 mod p(x)` << 1, x^241728 mod p(x)` << 1 + 0xab1695a8UL, 0x00000001UL, 0x34b626d2UL, 0x00000000UL, // x^240640 mod p(x)` << 1, x^240704 mod p(x)` << 1 + 0x90494bbaUL, 0x00000000UL, 0x4c53479aUL, 0x00000001UL, // x^239616 mod p(x)` << 1, x^239680 mod p(x)` << 1 + 0x123fb816UL, 0x00000001UL, 0xa6d179a4UL, 0x00000001UL, // x^238592 mod p(x)` << 1, x^238656 mod p(x)` << 1 + 0xe188c74cUL, 0x00000001UL, 0x5abd16b4UL, 0x00000001UL, // x^237568 mod p(x)` << 1, x^237632 mod p(x)` << 1 + 0xc2d3451cUL, 0x00000001UL, 0x018f9852UL, 0x00000000UL, // x^236544 mod p(x)` << 1, x^236608 mod p(x)` << 1 + 0xf55cf1caUL, 0x00000000UL, 0x1fb3084aUL, 0x00000000UL, // x^235520 mod p(x)` << 1, x^235584 mod p(x)` << 1 + 0xa0531540UL, 0x00000001UL, 0xc53dfb04UL, 0x00000000UL, // x^234496 mod p(x)` << 1, x^234560 mod p(x)` << 1 + 0x32cd7ebcUL, 0x00000001UL, 0xe10c9ad6UL, 0x00000000UL, // x^233472 mod p(x)` << 1, x^233536 mod p(x)` << 1 + 0x73ab7f36UL, 0x00000000UL, 0x25aa994aUL, 0x00000000UL, // x^232448 mod p(x)` << 1, x^232512 mod p(x)` << 1 + 0x41aed1c2UL, 0x00000000UL, 0xfa3a74c4UL, 0x00000000UL, // x^231424 mod p(x)` << 1, x^231488 mod p(x)` << 1 + 0x36c53800UL, 0x00000001UL, 0x33eb3f40UL, 0x00000000UL, // x^230400 mod p(x)` << 1, x^230464 mod p(x)` << 1 + 0x26835a30UL, 0x00000001UL, 0x7193f296UL, 0x00000001UL, // x^229376 mod p(x)` << 1, x^229440 mod p(x)` << 1 + 0x6241b502UL, 0x00000000UL, 0x43f6c86aUL, 0x00000000UL, // x^228352 mod p(x)` << 1, x^228416 mod p(x)` << 1 + 0xd5196ad4UL, 0x00000000UL, 0x6b513ec6UL, 0x00000001UL, // x^227328 mod p(x)` << 1, x^227392 mod p(x)` << 1 + 0x9cfa769aUL, 0x00000000UL, 0xc8f25b4eUL, 0x00000000UL, // x^226304 mod p(x)` << 1, x^226368 mod p(x)` << 1 + 0x920e5df4UL, 0x00000000UL, 0xa45048ecUL, 0x00000001UL, // x^225280 mod p(x)` << 1, x^225344 mod p(x)` << 1 + 0x69dc310eUL, 0x00000001UL, 0x0c441004UL, 0x00000000UL, // x^224256 mod p(x)` << 1, x^224320 mod p(x)` << 1 + 0x09fc331cUL, 0x00000000UL, 0x0e17cad6UL, 0x00000000UL, // x^223232 mod p(x)` << 1, x^223296 mod p(x)` << 1 + 0x0d94a81eUL, 0x00000001UL, 0x253ae964UL, 0x00000001UL, // x^222208 mod p(x)` << 1, x^222272 mod p(x)` << 1 + 0x27a20ab2UL, 0x00000000UL, 0xd7c88ebcUL, 0x00000001UL, // x^221184 mod p(x)` << 1, x^221248 mod p(x)` << 1 + 0x14f87504UL, 0x00000001UL, 0xe7ca913aUL, 0x00000001UL, // x^220160 mod p(x)` << 1, x^220224 mod p(x)` << 1 + 0x4b076d96UL, 0x00000000UL, 0x33ed078aUL, 0x00000000UL, // x^219136 mod p(x)` << 1, x^219200 mod p(x)` << 1 + 0xda4d1e74UL, 0x00000000UL, 0xe1839c78UL, 0x00000000UL, // x^218112 mod p(x)` << 1, x^218176 mod p(x)` << 1 + 0x1b81f672UL, 0x00000000UL, 0x322b267eUL, 0x00000001UL, // x^217088 mod p(x)` << 1, x^217152 mod p(x)` << 1 + 0x9367c988UL, 0x00000000UL, 0x638231b6UL, 0x00000000UL, // x^216064 mod p(x)` << 1, x^216128 mod p(x)` << 1 + 0x717214caUL, 0x00000001UL, 0xee7f16f4UL, 0x00000001UL, // x^215040 mod p(x)` << 1, x^215104 mod p(x)` << 1 + 0x9f47d820UL, 0x00000000UL, 0x17d9924aUL, 0x00000001UL, // x^214016 mod p(x)` << 1, x^214080 mod p(x)` << 1 + 0x0d9a47d2UL, 0x00000001UL, 0xe1a9e0c4UL, 0x00000000UL, // x^212992 mod p(x)` << 1, x^213056 mod p(x)` << 1 + 0xa696c58cUL, 0x00000000UL, 0x403731dcUL, 0x00000001UL, // x^211968 mod p(x)` << 1, x^212032 mod p(x)` << 1 + 0x2aa28ec6UL, 0x00000000UL, 0xa5ea9682UL, 0x00000001UL, // x^210944 mod p(x)` << 1, x^211008 mod p(x)` << 1 + 0xfe18fd9aUL, 0x00000001UL, 0x01c5c578UL, 0x00000001UL, // x^209920 mod p(x)` << 1, x^209984 mod p(x)` << 1 + 0x9d4fc1aeUL, 0x00000001UL, 0xdddf6494UL, 0x00000000UL, // x^208896 mod p(x)` << 1, x^208960 mod p(x)` << 1 + 0xba0e3deaUL, 0x00000001UL, 0xf1c3db28UL, 0x00000000UL, // x^207872 mod p(x)` << 1, x^207936 mod p(x)` << 1 + 0x74b59a5eUL, 0x00000000UL, 0x3112fb9cUL, 0x00000001UL, // x^206848 mod p(x)` << 1, x^206912 mod p(x)` << 1 + 0xf2b5ea98UL, 0x00000000UL, 0xb680b906UL, 0x00000000UL, // x^205824 mod p(x)` << 1, x^205888 mod p(x)` << 1 + 0x87132676UL, 0x00000001UL, 0x1a282932UL, 0x00000000UL, // x^204800 mod p(x)` << 1, x^204864 mod p(x)` << 1 + 0x0a8c6ad4UL, 0x00000001UL, 0x89406e7eUL, 0x00000000UL, // x^203776 mod p(x)` << 1, x^203840 mod p(x)` << 1 + 0xe21dfe70UL, 0x00000001UL, 0xdef6be8cUL, 0x00000001UL, // x^202752 mod p(x)` << 1, x^202816 mod p(x)` << 1 + 0xda0050e4UL, 0x00000001UL, 0x75258728UL, 0x00000000UL, // x^201728 mod p(x)` << 1, x^201792 mod p(x)` << 1 + 0x772172aeUL, 0x00000000UL, 0x9536090aUL, 0x00000001UL, // x^200704 mod p(x)` << 1, x^200768 mod p(x)` << 1 + 0xe47724aaUL, 0x00000000UL, 0xf2455bfcUL, 0x00000000UL, // x^199680 mod p(x)` << 1, x^199744 mod p(x)` << 1 + 0x3cd63ac4UL, 0x00000000UL, 0x8c40baf4UL, 0x00000001UL, // x^198656 mod p(x)` << 1, x^198720 mod p(x)` << 1 + 0xbf47d352UL, 0x00000001UL, 0x4cd390d4UL, 0x00000000UL, // x^197632 mod p(x)` << 1, x^197696 mod p(x)` << 1 + 0x8dc1d708UL, 0x00000001UL, 0xe4ece95aUL, 0x00000001UL, // x^196608 mod p(x)` << 1, x^196672 mod p(x)` << 1 + 0x2d4620a4UL, 0x00000000UL, 0x1a3ee918UL, 0x00000000UL, // x^195584 mod p(x)` << 1, x^195648 mod p(x)` << 1 + 0x58fd1740UL, 0x00000000UL, 0x7c652fb8UL, 0x00000000UL, // x^194560 mod p(x)` << 1, x^194624 mod p(x)` << 1 + 0xdadd9bfcUL, 0x00000000UL, 0x1c67842cUL, 0x00000001UL, // x^193536 mod p(x)` << 1, x^193600 mod p(x)` << 1 + 0xea2140beUL, 0x00000001UL, 0x254f759cUL, 0x00000000UL, // x^192512 mod p(x)` << 1, x^192576 mod p(x)` << 1 + 0x9de128baUL, 0x00000000UL, 0x7ece94caUL, 0x00000000UL, // x^191488 mod p(x)` << 1, x^191552 mod p(x)` << 1 + 0x3ac3aa8eUL, 0x00000001UL, 0x38f258c2UL, 0x00000000UL, // x^190464 mod p(x)` << 1, x^190528 mod p(x)` << 1 + 0x99980562UL, 0x00000000UL, 0xcdf17b00UL, 0x00000001UL, // x^189440 mod p(x)` << 1, x^189504 mod p(x)` << 1 + 0xc1579c86UL, 0x00000001UL, 0x1f882c16UL, 0x00000001UL, // x^188416 mod p(x)` << 1, x^188480 mod p(x)` << 1 + 0x68dbbf94UL, 0x00000000UL, 0x00093fc8UL, 0x00000001UL, // x^187392 mod p(x)` << 1, x^187456 mod p(x)` << 1 + 0x4509fb04UL, 0x00000000UL, 0xcd684f16UL, 0x00000001UL, // x^186368 mod p(x)` << 1, x^186432 mod p(x)` << 1 + 0x202f6398UL, 0x00000001UL, 0x4bc6a70aUL, 0x00000000UL, // x^185344 mod p(x)` << 1, x^185408 mod p(x)` << 1 + 0x3aea243eUL, 0x00000001UL, 0x4fc7e8e4UL, 0x00000000UL, // x^184320 mod p(x)` << 1, x^184384 mod p(x)` << 1 + 0xb4052ae6UL, 0x00000001UL, 0x30103f1cUL, 0x00000001UL, // x^183296 mod p(x)` << 1, x^183360 mod p(x)` << 1 + 0xcd2a0ae8UL, 0x00000001UL, 0x11b0024cUL, 0x00000001UL, // x^182272 mod p(x)` << 1, x^182336 mod p(x)` << 1 + 0xfe4aa8b4UL, 0x00000001UL, 0x0b3079daUL, 0x00000001UL, // x^181248 mod p(x)` << 1, x^181312 mod p(x)` << 1 + 0xd1559a42UL, 0x00000001UL, 0x0192bcc2UL, 0x00000001UL, // x^180224 mod p(x)` << 1, x^180288 mod p(x)` << 1 + 0xf3e05eccUL, 0x00000001UL, 0x74838d50UL, 0x00000000UL, // x^179200 mod p(x)` << 1, x^179264 mod p(x)` << 1 + 0x04ddd2ccUL, 0x00000001UL, 0x1b20f520UL, 0x00000000UL, // x^178176 mod p(x)` << 1, x^178240 mod p(x)` << 1 + 0x5393153cUL, 0x00000001UL, 0x50c3590aUL, 0x00000000UL, // x^177152 mod p(x)` << 1, x^177216 mod p(x)` << 1 + 0x57e942c6UL, 0x00000000UL, 0xb41cac8eUL, 0x00000000UL, // x^176128 mod p(x)` << 1, x^176192 mod p(x)` << 1 + 0x2c633850UL, 0x00000001UL, 0x0c72cc78UL, 0x00000000UL, // x^175104 mod p(x)` << 1, x^175168 mod p(x)` << 1 + 0xebcaae4cUL, 0x00000000UL, 0x30cdb032UL, 0x00000000UL, // x^174080 mod p(x)` << 1, x^174144 mod p(x)` << 1 + 0x3ee532a6UL, 0x00000001UL, 0x3e09fc32UL, 0x00000001UL, // x^173056 mod p(x)` << 1, x^173120 mod p(x)` << 1 + 0xbf0cbc7eUL, 0x00000001UL, 0x1ed624d2UL, 0x00000000UL, // x^172032 mod p(x)` << 1, x^172096 mod p(x)` << 1 + 0xd50b7a5aUL, 0x00000000UL, 0x781aee1aUL, 0x00000000UL, // x^171008 mod p(x)` << 1, x^171072 mod p(x)` << 1 + 0x02fca6e8UL, 0x00000000UL, 0xc4d8348cUL, 0x00000001UL, // x^169984 mod p(x)` << 1, x^170048 mod p(x)` << 1 + 0x7af40044UL, 0x00000000UL, 0x57a40336UL, 0x00000000UL, // x^168960 mod p(x)` << 1, x^169024 mod p(x)` << 1 + 0x16178744UL, 0x00000000UL, 0x85544940UL, 0x00000000UL, // x^167936 mod p(x)` << 1, x^168000 mod p(x)` << 1 + 0x4c177458UL, 0x00000001UL, 0x9cd21e80UL, 0x00000001UL, // x^166912 mod p(x)` << 1, x^166976 mod p(x)` << 1 + 0x1b6ddf04UL, 0x00000001UL, 0x3eb95bc0UL, 0x00000001UL, // x^165888 mod p(x)` << 1, x^165952 mod p(x)` << 1 + 0xf3e29cccUL, 0x00000001UL, 0xdfc9fdfcUL, 0x00000001UL, // x^164864 mod p(x)` << 1, x^164928 mod p(x)` << 1 + 0x35ae7562UL, 0x00000001UL, 0xcd028bc2UL, 0x00000000UL, // x^163840 mod p(x)` << 1, x^163904 mod p(x)` << 1 + 0x90ef812cUL, 0x00000001UL, 0x90db8c44UL, 0x00000000UL, // x^162816 mod p(x)` << 1, x^162880 mod p(x)` << 1 + 0x67a2c786UL, 0x00000000UL, 0x0010a4ceUL, 0x00000001UL, // x^161792 mod p(x)` << 1, x^161856 mod p(x)` << 1 + 0x48b9496cUL, 0x00000000UL, 0xc8f4c72cUL, 0x00000001UL, // x^160768 mod p(x)` << 1, x^160832 mod p(x)` << 1 + 0x5a422de6UL, 0x00000001UL, 0x1c26170cUL, 0x00000000UL, // x^159744 mod p(x)` << 1, x^159808 mod p(x)` << 1 + 0xef0e3640UL, 0x00000001UL, 0xe3fccf68UL, 0x00000000UL, // x^158720 mod p(x)` << 1, x^158784 mod p(x)` << 1 + 0x006d2d26UL, 0x00000001UL, 0xd513ed24UL, 0x00000000UL, // x^157696 mod p(x)` << 1, x^157760 mod p(x)` << 1 + 0x170d56d6UL, 0x00000001UL, 0x141beadaUL, 0x00000000UL, // x^156672 mod p(x)` << 1, x^156736 mod p(x)` << 1 + 0xa5fb613cUL, 0x00000000UL, 0x1071aea0UL, 0x00000001UL, // x^155648 mod p(x)` << 1, x^155712 mod p(x)` << 1 + 0x40bbf7fcUL, 0x00000000UL, 0x2e19080aUL, 0x00000001UL, // x^154624 mod p(x)` << 1, x^154688 mod p(x)` << 1 + 0x6ac3a5b2UL, 0x00000001UL, 0x00ecf826UL, 0x00000001UL, // x^153600 mod p(x)` << 1, x^153664 mod p(x)` << 1 + 0xabf16230UL, 0x00000000UL, 0x69b09412UL, 0x00000000UL, // x^152576 mod p(x)` << 1, x^152640 mod p(x)` << 1 + 0xebe23facUL, 0x00000001UL, 0x22297bacUL, 0x00000001UL, // x^151552 mod p(x)` << 1, x^151616 mod p(x)` << 1 + 0x8b6a0894UL, 0x00000000UL, 0xe9e4b068UL, 0x00000000UL, // x^150528 mod p(x)` << 1, x^150592 mod p(x)` << 1 + 0x288ea478UL, 0x00000001UL, 0x4b38651aUL, 0x00000000UL, // x^149504 mod p(x)` << 1, x^149568 mod p(x)` << 1 + 0x6619c442UL, 0x00000001UL, 0x468360e2UL, 0x00000001UL, // x^148480 mod p(x)` << 1, x^148544 mod p(x)` << 1 + 0x86230038UL, 0x00000000UL, 0x121c2408UL, 0x00000000UL, // x^147456 mod p(x)` << 1, x^147520 mod p(x)` << 1 + 0x7746a756UL, 0x00000001UL, 0xda7e7d08UL, 0x00000000UL, // x^146432 mod p(x)` << 1, x^146496 mod p(x)` << 1 + 0x91b8f8f8UL, 0x00000001UL, 0x058d7652UL, 0x00000001UL, // x^145408 mod p(x)` << 1, x^145472 mod p(x)` << 1 + 0x8e167708UL, 0x00000000UL, 0x4a098a90UL, 0x00000001UL, // x^144384 mod p(x)` << 1, x^144448 mod p(x)` << 1 + 0x48b22d54UL, 0x00000001UL, 0x20dbe72eUL, 0x00000000UL, // x^143360 mod p(x)` << 1, x^143424 mod p(x)` << 1 + 0x44ba2c3cUL, 0x00000000UL, 0x1e7323e8UL, 0x00000001UL, // x^142336 mod p(x)` << 1, x^142400 mod p(x)` << 1 + 0xb54d2b52UL, 0x00000000UL, 0xd5d4bf94UL, 0x00000000UL, // x^141312 mod p(x)` << 1, x^141376 mod p(x)` << 1 + 0x05a4fd8aUL, 0x00000000UL, 0x99d8746cUL, 0x00000001UL, // x^140288 mod p(x)` << 1, x^140352 mod p(x)` << 1 + 0x39f9fc46UL, 0x00000001UL, 0xce9ca8a0UL, 0x00000000UL, // x^139264 mod p(x)` << 1, x^139328 mod p(x)` << 1 + 0x5a1fa824UL, 0x00000001UL, 0x136edeceUL, 0x00000000UL, // x^138240 mod p(x)` << 1, x^138304 mod p(x)` << 1 + 0x0a61ae4cUL, 0x00000000UL, 0x9b92a068UL, 0x00000001UL, // x^137216 mod p(x)` << 1, x^137280 mod p(x)` << 1 + 0x45e9113eUL, 0x00000001UL, 0x71d62206UL, 0x00000000UL, // x^136192 mod p(x)` << 1, x^136256 mod p(x)` << 1 + 0x6a348448UL, 0x00000000UL, 0xdfc50158UL, 0x00000000UL, // x^135168 mod p(x)` << 1, x^135232 mod p(x)` << 1 + 0x4d80a08cUL, 0x00000000UL, 0x517626bcUL, 0x00000001UL, // x^134144 mod p(x)` << 1, x^134208 mod p(x)` << 1 + 0x4b6837a0UL, 0x00000001UL, 0x48d1e4faUL, 0x00000001UL, // x^133120 mod p(x)` << 1, x^133184 mod p(x)` << 1 + 0x6896a7fcUL, 0x00000001UL, 0x94d8266eUL, 0x00000000UL, // x^132096 mod p(x)` << 1, x^132160 mod p(x)` << 1 + 0x4f187140UL, 0x00000001UL, 0x606c5e34UL, 0x00000000UL, // x^131072 mod p(x)` << 1, x^131136 mod p(x)` << 1 + 0x9581b9daUL, 0x00000001UL, 0x9766beaaUL, 0x00000001UL, // x^130048 mod p(x)` << 1, x^130112 mod p(x)` << 1 + 0x091bc984UL, 0x00000001UL, 0xd80c506cUL, 0x00000001UL, // x^129024 mod p(x)` << 1, x^129088 mod p(x)` << 1 + 0x1067223cUL, 0x00000000UL, 0x1e73837cUL, 0x00000000UL, // x^128000 mod p(x)` << 1, x^128064 mod p(x)` << 1 + 0xab16ea02UL, 0x00000001UL, 0x64d587deUL, 0x00000000UL, // x^126976 mod p(x)` << 1, x^127040 mod p(x)` << 1 + 0x3c4598a8UL, 0x00000001UL, 0xf4a507b0UL, 0x00000000UL, // x^125952 mod p(x)` << 1, x^126016 mod p(x)` << 1 + 0xb3735430UL, 0x00000000UL, 0x40e342fcUL, 0x00000000UL, // x^124928 mod p(x)` << 1, x^124992 mod p(x)` << 1 + 0xbb3fc0c0UL, 0x00000001UL, 0xd5ad9c3aUL, 0x00000001UL, // x^123904 mod p(x)` << 1, x^123968 mod p(x)` << 1 + 0x570ae19cUL, 0x00000001UL, 0x94a691a4UL, 0x00000000UL, // x^122880 mod p(x)` << 1, x^122944 mod p(x)` << 1 + 0xea910712UL, 0x00000001UL, 0x271ecdfaUL, 0x00000001UL, // x^121856 mod p(x)` << 1, x^121920 mod p(x)` << 1 + 0x67127128UL, 0x00000001UL, 0x9e54475aUL, 0x00000000UL, // x^120832 mod p(x)` << 1, x^120896 mod p(x)` << 1 + 0x19e790a2UL, 0x00000000UL, 0xc9c099eeUL, 0x00000000UL, // x^119808 mod p(x)` << 1, x^119872 mod p(x)` << 1 + 0x3788f710UL, 0x00000000UL, 0x9a2f736cUL, 0x00000000UL, // x^118784 mod p(x)` << 1, x^118848 mod p(x)` << 1 + 0x682a160eUL, 0x00000001UL, 0xbb9f4996UL, 0x00000000UL, // x^117760 mod p(x)` << 1, x^117824 mod p(x)` << 1 + 0x7f0ebd2eUL, 0x00000000UL, 0xdb688050UL, 0x00000001UL, // x^116736 mod p(x)` << 1, x^116800 mod p(x)` << 1 + 0x2b032080UL, 0x00000000UL, 0xe9b10af4UL, 0x00000000UL, // x^115712 mod p(x)` << 1, x^115776 mod p(x)` << 1 + 0xcfd1664aUL, 0x00000000UL, 0x2d4545e4UL, 0x00000001UL, // x^114688 mod p(x)` << 1, x^114752 mod p(x)` << 1 + 0xaa1181c2UL, 0x00000000UL, 0x0361139cUL, 0x00000000UL, // x^113664 mod p(x)` << 1, x^113728 mod p(x)` << 1 + 0xddd08002UL, 0x00000000UL, 0xa5a1a3a8UL, 0x00000001UL, // x^112640 mod p(x)` << 1, x^112704 mod p(x)` << 1 + 0xe8dd0446UL, 0x00000000UL, 0x6844e0b0UL, 0x00000000UL, // x^111616 mod p(x)` << 1, x^111680 mod p(x)` << 1 + 0xbbd94a00UL, 0x00000001UL, 0xc3762f28UL, 0x00000000UL, // x^110592 mod p(x)` << 1, x^110656 mod p(x)` << 1 + 0xab6cd180UL, 0x00000000UL, 0xd26287a2UL, 0x00000001UL, // x^109568 mod p(x)` << 1, x^109632 mod p(x)` << 1 + 0x31803ce2UL, 0x00000000UL, 0xf6f0bba8UL, 0x00000001UL, // x^108544 mod p(x)` << 1, x^108608 mod p(x)` << 1 + 0x24f40b0cUL, 0x00000000UL, 0x2ffabd62UL, 0x00000000UL, // x^107520 mod p(x)` << 1, x^107584 mod p(x)` << 1 + 0xba1d9834UL, 0x00000001UL, 0xfb4516b8UL, 0x00000000UL, // x^106496 mod p(x)` << 1, x^106560 mod p(x)` << 1 + 0x04de61aaUL, 0x00000001UL, 0x8cfa961cUL, 0x00000001UL, // x^105472 mod p(x)` << 1, x^105536 mod p(x)` << 1 + 0x13e40d46UL, 0x00000001UL, 0x9e588d52UL, 0x00000001UL, // x^104448 mod p(x)` << 1, x^104512 mod p(x)` << 1 + 0x415598a0UL, 0x00000001UL, 0x180f0bbcUL, 0x00000001UL, // x^103424 mod p(x)` << 1, x^103488 mod p(x)` << 1 + 0xbf6c8c90UL, 0x00000000UL, 0xe1d9177aUL, 0x00000000UL, // x^102400 mod p(x)` << 1, x^102464 mod p(x)` << 1 + 0x788b0504UL, 0x00000001UL, 0x05abc27cUL, 0x00000001UL, // x^101376 mod p(x)` << 1, x^101440 mod p(x)` << 1 + 0x38385d02UL, 0x00000000UL, 0x972e4a58UL, 0x00000000UL, // x^100352 mod p(x)` << 1, x^100416 mod p(x)` << 1 + 0xb6c83844UL, 0x00000001UL, 0x83499a5eUL, 0x00000001UL, // x^99328 mod p(x)` << 1, x^99392 mod p(x)` << 1 + 0x51061a8aUL, 0x00000000UL, 0xc96a8ccaUL, 0x00000001UL, // x^98304 mod p(x)` << 1, x^98368 mod p(x)` << 1 + 0x7351388aUL, 0x00000001UL, 0xa1a5b60cUL, 0x00000001UL, // x^97280 mod p(x)` << 1, x^97344 mod p(x)` << 1 + 0x32928f92UL, 0x00000001UL, 0xe4b6ac9cUL, 0x00000000UL, // x^96256 mod p(x)` << 1, x^96320 mod p(x)` << 1 + 0xe6b4f48aUL, 0x00000000UL, 0x807e7f5aUL, 0x00000001UL, // x^95232 mod p(x)` << 1, x^95296 mod p(x)` << 1 + 0x39d15e90UL, 0x00000000UL, 0x7a7e3bc8UL, 0x00000001UL, // x^94208 mod p(x)` << 1, x^94272 mod p(x)` << 1 + 0x312d6074UL, 0x00000000UL, 0xd73975daUL, 0x00000000UL, // x^93184 mod p(x)` << 1, x^93248 mod p(x)` << 1 + 0x7bbb2cc4UL, 0x00000001UL, 0x7375d038UL, 0x00000001UL, // x^92160 mod p(x)` << 1, x^92224 mod p(x)` << 1 + 0x6ded3e18UL, 0x00000001UL, 0x193680bcUL, 0x00000000UL, // x^91136 mod p(x)` << 1, x^91200 mod p(x)` << 1 + 0xf1638b16UL, 0x00000000UL, 0x999b06f6UL, 0x00000000UL, // x^90112 mod p(x)` << 1, x^90176 mod p(x)` << 1 + 0xd38b9eccUL, 0x00000001UL, 0xf685d2b8UL, 0x00000001UL, // x^89088 mod p(x)` << 1, x^89152 mod p(x)` << 1 + 0x8b8d09dcUL, 0x00000001UL, 0xf4ecbed2UL, 0x00000001UL, // x^88064 mod p(x)` << 1, x^88128 mod p(x)` << 1 + 0xe7bc27d2UL, 0x00000000UL, 0xba16f1a0UL, 0x00000000UL, // x^87040 mod p(x)` << 1, x^87104 mod p(x)` << 1 + 0x275e1e96UL, 0x00000000UL, 0x15aceac4UL, 0x00000001UL, // x^86016 mod p(x)` << 1, x^86080 mod p(x)` << 1 + 0xe2e3031eUL, 0x00000000UL, 0xaeff6292UL, 0x00000001UL, // x^84992 mod p(x)` << 1, x^85056 mod p(x)` << 1 + 0x041c84d8UL, 0x00000001UL, 0x9640124cUL, 0x00000000UL, // x^83968 mod p(x)` << 1, x^84032 mod p(x)` << 1 + 0x706ce672UL, 0x00000000UL, 0x14f41f02UL, 0x00000001UL, // x^82944 mod p(x)` << 1, x^83008 mod p(x)` << 1 + 0x5d5070daUL, 0x00000001UL, 0x9c5f3586UL, 0x00000000UL, // x^81920 mod p(x)` << 1, x^81984 mod p(x)` << 1 + 0x38f9493aUL, 0x00000000UL, 0x878275faUL, 0x00000001UL, // x^80896 mod p(x)` << 1, x^80960 mod p(x)` << 1 + 0xa3348a76UL, 0x00000000UL, 0xddc42ce8UL, 0x00000000UL, // x^79872 mod p(x)` << 1, x^79936 mod p(x)` << 1 + 0xad0aab92UL, 0x00000001UL, 0x81d2c73aUL, 0x00000001UL, // x^78848 mod p(x)` << 1, x^78912 mod p(x)` << 1 + 0x9e85f712UL, 0x00000001UL, 0x41c9320aUL, 0x00000001UL, // x^77824 mod p(x)` << 1, x^77888 mod p(x)` << 1 + 0x5a871e76UL, 0x00000000UL, 0x5235719aUL, 0x00000001UL, // x^76800 mod p(x)` << 1, x^76864 mod p(x)` << 1 + 0x7249c662UL, 0x00000001UL, 0xbe27d804UL, 0x00000000UL, // x^75776 mod p(x)` << 1, x^75840 mod p(x)` << 1 + 0x3a084712UL, 0x00000000UL, 0x6242d45aUL, 0x00000000UL, // x^74752 mod p(x)` << 1, x^74816 mod p(x)` << 1 + 0xed438478UL, 0x00000000UL, 0x9a53638eUL, 0x00000000UL, // x^73728 mod p(x)` << 1, x^73792 mod p(x)` << 1 + 0xabac34ccUL, 0x00000000UL, 0x001ecfb6UL, 0x00000001UL, // x^72704 mod p(x)` << 1, x^72768 mod p(x)` << 1 + 0x5f35ef3eUL, 0x00000000UL, 0x6d7c2d64UL, 0x00000001UL, // x^71680 mod p(x)` << 1, x^71744 mod p(x)` << 1 + 0x47d6608cUL, 0x00000000UL, 0xd0ce46c0UL, 0x00000001UL, // x^70656 mod p(x)` << 1, x^70720 mod p(x)` << 1 + 0x2d01470eUL, 0x00000000UL, 0x24c907b4UL, 0x00000001UL, // x^69632 mod p(x)` << 1, x^69696 mod p(x)` << 1 + 0x58bbc7b0UL, 0x00000001UL, 0x18a555caUL, 0x00000000UL, // x^68608 mod p(x)` << 1, x^68672 mod p(x)` << 1 + 0xc0a23e8eUL, 0x00000000UL, 0x6b0980bcUL, 0x00000000UL, // x^67584 mod p(x)` << 1, x^67648 mod p(x)` << 1 + 0xebd85c88UL, 0x00000001UL, 0x8bbba964UL, 0x00000000UL, // x^66560 mod p(x)` << 1, x^66624 mod p(x)` << 1 + 0x9ee20bb2UL, 0x00000001UL, 0x070a5a1eUL, 0x00000001UL, // x^65536 mod p(x)` << 1, x^65600 mod p(x)` << 1 + 0xacabf2d6UL, 0x00000001UL, 0x2204322aUL, 0x00000000UL, // x^64512 mod p(x)` << 1, x^64576 mod p(x)` << 1 + 0xb7963d56UL, 0x00000001UL, 0xa27524d0UL, 0x00000000UL, // x^63488 mod p(x)` << 1, x^63552 mod p(x)` << 1 + 0x7bffa1feUL, 0x00000001UL, 0x20b1e4baUL, 0x00000000UL, // x^62464 mod p(x)` << 1, x^62528 mod p(x)` << 1 + 0x1f15333eUL, 0x00000000UL, 0x32cc27fcUL, 0x00000000UL, // x^61440 mod p(x)` << 1, x^61504 mod p(x)` << 1 + 0x8593129eUL, 0x00000001UL, 0x44dd22b8UL, 0x00000000UL, // x^60416 mod p(x)` << 1, x^60480 mod p(x)` << 1 + 0x9cb32602UL, 0x00000001UL, 0xdffc9e0aUL, 0x00000000UL, // x^59392 mod p(x)` << 1, x^59456 mod p(x)` << 1 + 0x42b05cc8UL, 0x00000001UL, 0xb7a0ed14UL, 0x00000001UL, // x^58368 mod p(x)` << 1, x^58432 mod p(x)` << 1 + 0xbe49e7a4UL, 0x00000001UL, 0xc7842488UL, 0x00000000UL, // x^57344 mod p(x)` << 1, x^57408 mod p(x)` << 1 + 0x08f69d6cUL, 0x00000001UL, 0xc02a4feeUL, 0x00000001UL, // x^56320 mod p(x)` << 1, x^56384 mod p(x)` << 1 + 0x6c0971f0UL, 0x00000000UL, 0x3c273778UL, 0x00000000UL, // x^55296 mod p(x)` << 1, x^55360 mod p(x)` << 1 + 0x5b16467aUL, 0x00000000UL, 0xd63f8894UL, 0x00000001UL, // x^54272 mod p(x)` << 1, x^54336 mod p(x)` << 1 + 0x551a628eUL, 0x00000001UL, 0x6be557d6UL, 0x00000000UL, // x^53248 mod p(x)` << 1, x^53312 mod p(x)` << 1 + 0x9e42ea92UL, 0x00000001UL, 0x6a7806eaUL, 0x00000000UL, // x^52224 mod p(x)` << 1, x^52288 mod p(x)` << 1 + 0x2fa83ff2UL, 0x00000001UL, 0x6155aa0cUL, 0x00000001UL, // x^51200 mod p(x)` << 1, x^51264 mod p(x)` << 1 + 0x1ca9cde0UL, 0x00000001UL, 0x908650acUL, 0x00000000UL, // x^50176 mod p(x)` << 1, x^50240 mod p(x)` << 1 + 0xc8e5cd74UL, 0x00000000UL, 0xaa5a8084UL, 0x00000000UL, // x^49152 mod p(x)` << 1, x^49216 mod p(x)` << 1 + 0x96c27f0cUL, 0x00000000UL, 0x91bb500aUL, 0x00000001UL, // x^48128 mod p(x)` << 1, x^48192 mod p(x)` << 1 + 0x2baed926UL, 0x00000000UL, 0x64e9bed0UL, 0x00000000UL, // x^47104 mod p(x)` << 1, x^47168 mod p(x)` << 1 + 0x7c8de8d2UL, 0x00000001UL, 0x9444f302UL, 0x00000000UL, // x^46080 mod p(x)` << 1, x^46144 mod p(x)` << 1 + 0xd43d6068UL, 0x00000000UL, 0x9db07d3cUL, 0x00000001UL, // x^45056 mod p(x)` << 1, x^45120 mod p(x)` << 1 + 0xcb2c4b26UL, 0x00000000UL, 0x359e3e6eUL, 0x00000001UL, // x^44032 mod p(x)` << 1, x^44096 mod p(x)` << 1 + 0x45b8da26UL, 0x00000001UL, 0xe4f10dd2UL, 0x00000001UL, // x^43008 mod p(x)` << 1, x^43072 mod p(x)` << 1 + 0x8fff4b08UL, 0x00000001UL, 0x24f5735eUL, 0x00000001UL, // x^41984 mod p(x)` << 1, x^42048 mod p(x)` << 1 + 0x50b58ed0UL, 0x00000001UL, 0x24760a4cUL, 0x00000001UL, // x^40960 mod p(x)` << 1, x^41024 mod p(x)` << 1 + 0x549f39bcUL, 0x00000001UL, 0x0f1fc186UL, 0x00000000UL, // x^39936 mod p(x)` << 1, x^40000 mod p(x)` << 1 + 0xef4d2f42UL, 0x00000000UL, 0x150e4cc4UL, 0x00000000UL, // x^38912 mod p(x)` << 1, x^38976 mod p(x)` << 1 + 0xb1468572UL, 0x00000001UL, 0x2a6204e8UL, 0x00000000UL, // x^37888 mod p(x)` << 1, x^37952 mod p(x)` << 1 + 0x3d7403b2UL, 0x00000001UL, 0xbeb1d432UL, 0x00000000UL, // x^36864 mod p(x)` << 1, x^36928 mod p(x)` << 1 + 0xa4681842UL, 0x00000001UL, 0x35f3f1f0UL, 0x00000001UL, // x^35840 mod p(x)` << 1, x^35904 mod p(x)` << 1 + 0x67714492UL, 0x00000001UL, 0x74fe2232UL, 0x00000000UL, // x^34816 mod p(x)` << 1, x^34880 mod p(x)` << 1 + 0xe599099aUL, 0x00000001UL, 0x1ac6e2baUL, 0x00000000UL, // x^33792 mod p(x)` << 1, x^33856 mod p(x)` << 1 + 0xfe128194UL, 0x00000000UL, 0x13fca91eUL, 0x00000000UL, // x^32768 mod p(x)` << 1, x^32832 mod p(x)` << 1 + 0x77e8b990UL, 0x00000000UL, 0x83f4931eUL, 0x00000001UL, // x^31744 mod p(x)` << 1, x^31808 mod p(x)` << 1 + 0xa267f63aUL, 0x00000001UL, 0xb6d9b4e4UL, 0x00000000UL, // x^30720 mod p(x)` << 1, x^30784 mod p(x)` << 1 + 0x945c245aUL, 0x00000001UL, 0xb5188656UL, 0x00000000UL, // x^29696 mod p(x)` << 1, x^29760 mod p(x)` << 1 + 0x49002e76UL, 0x00000001UL, 0x27a81a84UL, 0x00000000UL, // x^28672 mod p(x)` << 1, x^28736 mod p(x)` << 1 + 0xbb8310a4UL, 0x00000001UL, 0x25699258UL, 0x00000001UL, // x^27648 mod p(x)` << 1, x^27712 mod p(x)` << 1 + 0x9ec60bccUL, 0x00000001UL, 0xb23de796UL, 0x00000001UL, // x^26624 mod p(x)` << 1, x^26688 mod p(x)` << 1 + 0x2d8590aeUL, 0x00000001UL, 0xfe4365dcUL, 0x00000000UL, // x^25600 mod p(x)` << 1, x^25664 mod p(x)` << 1 + 0x65b00684UL, 0x00000000UL, 0xc68f497aUL, 0x00000000UL, // x^24576 mod p(x)` << 1, x^24640 mod p(x)` << 1 + 0x5e5aeadcUL, 0x00000001UL, 0xfbf521eeUL, 0x00000000UL, // x^23552 mod p(x)` << 1, x^23616 mod p(x)` << 1 + 0xb77ff2b0UL, 0x00000000UL, 0x5eac3378UL, 0x00000001UL, // x^22528 mod p(x)` << 1, x^22592 mod p(x)` << 1 + 0x88da2ff6UL, 0x00000001UL, 0x34914b90UL, 0x00000001UL, // x^21504 mod p(x)` << 1, x^21568 mod p(x)` << 1 + 0x63da929aUL, 0x00000000UL, 0x16335cfeUL, 0x00000000UL, // x^20480 mod p(x)` << 1, x^20544 mod p(x)` << 1 + 0x389caa80UL, 0x00000001UL, 0x0372d10cUL, 0x00000001UL, // x^19456 mod p(x)` << 1, x^19520 mod p(x)` << 1 + 0x3db599d2UL, 0x00000001UL, 0x5097b908UL, 0x00000001UL, // x^18432 mod p(x)` << 1, x^18496 mod p(x)` << 1 + 0x22505a86UL, 0x00000001UL, 0x227a7572UL, 0x00000001UL, // x^17408 mod p(x)` << 1, x^17472 mod p(x)` << 1 + 0x6bd72746UL, 0x00000001UL, 0x9a8f75c0UL, 0x00000000UL, // x^16384 mod p(x)` << 1, x^16448 mod p(x)` << 1 + 0xc3faf1d4UL, 0x00000001UL, 0x682c77a2UL, 0x00000000UL, // x^15360 mod p(x)` << 1, x^15424 mod p(x)` << 1 + 0x111c826cUL, 0x00000001UL, 0x231f091cUL, 0x00000000UL, // x^14336 mod p(x)` << 1, x^14400 mod p(x)` << 1 + 0x153e9fb2UL, 0x00000000UL, 0x7d4439f2UL, 0x00000000UL, // x^13312 mod p(x)` << 1, x^13376 mod p(x)` << 1 + 0x2b1f7b60UL, 0x00000000UL, 0x7e221efcUL, 0x00000001UL, // x^12288 mod p(x)` << 1, x^12352 mod p(x)` << 1 + 0xb1dba570UL, 0x00000000UL, 0x67457c38UL, 0x00000001UL, // x^11264 mod p(x)` << 1, x^11328 mod p(x)` << 1 + 0xf6397b76UL, 0x00000001UL, 0xbdf081c4UL, 0x00000000UL, // x^10240 mod p(x)` << 1, x^10304 mod p(x)` << 1 + 0x56335214UL, 0x00000001UL, 0x6286d6b0UL, 0x00000001UL, // x^9216 mod p(x)` << 1, x^9280 mod p(x)` << 1 + 0xd70e3986UL, 0x00000001UL, 0xc84f001cUL, 0x00000000UL, // x^8192 mod p(x)` << 1, x^8256 mod p(x)` << 1 + 0x3701a774UL, 0x00000000UL, 0x64efe7c0UL, 0x00000000UL, // x^7168 mod p(x)` << 1, x^7232 mod p(x)` << 1 + 0xac81ef72UL, 0x00000000UL, 0x0ac2d904UL, 0x00000000UL, // x^6144 mod p(x)` << 1, x^6208 mod p(x)` << 1 + 0x33212464UL, 0x00000001UL, 0xfd226d14UL, 0x00000000UL, // x^5120 mod p(x)` << 1, x^5184 mod p(x)` << 1 + 0xe4e45610UL, 0x00000000UL, 0x1cfd42e0UL, 0x00000001UL, // x^4096 mod p(x)` << 1, x^4160 mod p(x)` << 1 + 0x0c1bd370UL, 0x00000000UL, 0x6e5a5678UL, 0x00000001UL, // x^3072 mod p(x)` << 1, x^3136 mod p(x)` << 1 + 0xa7b9e7a6UL, 0x00000001UL, 0xd888fe22UL, 0x00000001UL, // x^2048 mod p(x)` << 1, x^2112 mod p(x)` << 1 + 0x7d657a10UL, 0x00000000UL, 0xaf77fcd4UL, 0x00000001UL, // x^1024 mod p(x)` << 1, x^1088 mod p(x)` << 1 + + // Reduce final 1024-2048 bits to 64 bits, shifting 32 bits to include the trailing 32 bits of zeros + 0xec447f11UL, 0x99168a18UL, 0x13e8221eUL, 0xed837b26UL, // x^2048 mod p(x)`, x^2016 mod p(x)`, x^1984 mod p(x)`, x^1952 mod p(x)` + 0x8fd2cd3cUL, 0xe23e954eUL, 0x47b9ce5aUL, 0xc8acdd81UL, // x^1920 mod p(x)`, x^1888 mod p(x)`, x^1856 mod p(x)`, x^1824 mod p(x)` + 0x6b1d2b53UL, 0x92f8befeUL, 0xd4277e25UL, 0xd9ad6d87UL, // x^1792 mod p(x)`, x^1760 mod p(x)`, x^1728 mod p(x)`, x^1696 mod p(x)` + 0x291ea462UL, 0xf38a3556UL, 0x33fbca3bUL, 0xc10ec5e0UL, // x^1664 mod p(x)`, x^1632 mod p(x)`, x^1600 mod p(x)`, x^1568 mod p(x)` + 0x62b6ca4bUL, 0x974ac562UL, 0x82e02e2fUL, 0xc0b55b0eUL, // x^1536 mod p(x)`, x^1504 mod p(x)`, x^1472 mod p(x)`, x^1440 mod p(x)` + 0x784d2a56UL, 0x855712b3UL, 0xe172334dUL, 0x71aa1df0UL, // x^1408 mod p(x)`, x^1376 mod p(x)`, x^1344 mod p(x)`, x^1312 mod p(x)` + 0x0eaee722UL, 0xa5abe9f8UL, 0x3969324dUL, 0xfee3053eUL, // x^1280 mod p(x)`, x^1248 mod p(x)`, x^1216 mod p(x)`, x^1184 mod p(x)` + 0xdb54814cUL, 0x1fa0943dUL, 0x3eb2bd08UL, 0xf44779b9UL, // x^1152 mod p(x)`, x^1120 mod p(x)`, x^1088 mod p(x)`, x^1056 mod p(x)` + 0xd7bbfe6aUL, 0xa53ff440UL, 0x00cc3374UL, 0xf5449b3fUL, // x^1024 mod p(x)`, x^992 mod p(x)`, x^960 mod p(x)`, x^928 mod p(x)` + 0x6325605cUL, 0xebe7e356UL, 0xd777606eUL, 0x6f8346e1UL, // x^896 mod p(x)`, x^864 mod p(x)`, x^832 mod p(x)`, x^800 mod p(x)` + 0xe5b592b8UL, 0xc65a272cUL, 0xc0b95347UL, 0xe3ab4f2aUL, // x^768 mod p(x)`, x^736 mod p(x)`, x^704 mod p(x)`, x^672 mod p(x)` + 0x4721589fUL, 0x5705a9caUL, 0x329ecc11UL, 0xaa2215eaUL, // x^640 mod p(x)`, x^608 mod p(x)`, x^576 mod p(x)`, x^544 mod p(x)` + 0x88d14467UL, 0xe3720acbUL, 0xd95efd26UL, 0x1ed8f66eUL, // x^512 mod p(x)`, x^480 mod p(x)`, x^448 mod p(x)`, x^416 mod p(x)` + 0x15141c31UL, 0xba1aca03UL, 0xa700e96aUL, 0x78ed02d5UL, // x^384 mod p(x)`, x^352 mod p(x)`, x^320 mod p(x)`, x^288 mod p(x)` + 0xed627daeUL, 0xad2a31b3UL, 0x32b39da3UL, 0xba8ccbe8UL, // x^256 mod p(x)`, x^224 mod p(x)`, x^192 mod p(x)`, x^160 mod p(x)` + 0xa06a2517UL, 0x6655004fUL, 0xb1e6b092UL, 0xedb88320UL // x^128 mod p(x)`, x^96 mod p(x)`, x^64 mod p(x)`, x^32 mod p(x)` + }; + + juint* ptr = (juint*) malloc(sizeof(juint) * CRC32_CONSTANTS_SIZE); + guarantee(((intptr_t)ptr & 0xF) == 0, "16-byte alignment needed"); + guarantee(ptr != NULL, "allocation error of a crc table"); + memcpy((void*)ptr, constants, sizeof(juint) * CRC32_CONSTANTS_SIZE); + return ptr; +} + +juint* StubRoutines::ppc64::generate_crc_barret_constants() { + juint barret_constants[CRC32_BARRET_CONSTANTS] = { + 0xf7011641UL, 0x00000001UL, 0x00000000UL, 0x00000000UL, + 0xdb710641UL, 0x00000001UL, 0x00000000UL, 0x00000000UL + }; + juint* ptr = (juint*) malloc(sizeof(juint) * CRC32_CONSTANTS_SIZE); + guarantee(((intptr_t)ptr & 0xF) == 0, "16-byte alignment needed"); + guarantee(ptr != NULL, "allocation error of a crc table"); + memcpy((void*) ptr, barret_constants, sizeof(juint) * CRC32_BARRET_CONSTANTS); + return ptr; +} + // CRC32 Intrinsics. /** * crc_table[] from jdk/src/share/native/java/util/zip/zlib-1.2.8/crc32.h @@ -477,3 +782,7 @@ juint StubRoutines::ppc64::_crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE] = { #endif } }; + +juint* StubRoutines::ppc64::_constants = StubRoutines::ppc64::generate_crc_constants(); + +juint* StubRoutines::ppc64::_barret_constants = StubRoutines::ppc64::generate_crc_barret_constants(); diff --git a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp index c37887fd9cf..959ee898504 100644 --- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp @@ -1544,6 +1544,12 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { __ fence(); } + if (CheckJNICalls) { + // clear_pending_jni_exception_check + __ load_const_optimized(R0, 0L); + __ st_ptr(R0, JavaThread::pending_jni_exception_check_fn_offset(), R16_thread); + } + __ reset_last_Java_frame(); // Jvmdi/jvmpi support. Whether we've got an exception pending or diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp index d83c3cd3b73..6162bafd1ab 100644 --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp @@ -230,6 +230,11 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseGHASHIntrinsics, false); } + if (UseFMA) { + warning("FMA instructions are not available on this CPU"); + FLAG_SET_DEFAULT(UseFMA, false); + } + if (UseSHA) { warning("SHA instructions are not available on this CPU"); FLAG_SET_DEFAULT(UseSHA, false); @@ -274,7 +279,14 @@ void VM_Version::initialize() { } bool os_too_old = true; #ifdef AIX - if (os::Aix::os_version() >= 0x0701031e) { // at least AIX 7.1.3.30 + // Actually, this is supported since AIX 7.1.. Unfortunately, this first + // contained bugs, so that it can only be enabled after AIX 7.1.3.30. + // The Java property os.version, which is used in RTM tests to decide + // whether the feature is available, only knows major and minor versions. + // We don't want to change this property, as user code might depend on it. + // So the tests can not check on subversion 3.30, and we only enable RTM + // with AIX 7.2. + if (os::Aix::os_version() >= 0x07020000) { // At least AIX 7.2. os_too_old = false; } #endif diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp index f4d84c8dd5d..36d3059739c 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp @@ -147,10 +147,11 @@ LIR_Opr LIRGenerator::safepoint_poll_register() { LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index, int shift, int disp, BasicType type) { assert(base->is_register(), "must be"); + intx large_disp = disp; // accumulate fixed displacements if (index->is_constant()) { - disp += index->as_constant_ptr()->as_jint() << shift; + large_disp += (intx)(index->as_constant_ptr()->as_jint()) << shift; index = LIR_OprFact::illegalOpr; } @@ -161,31 +162,31 @@ LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index, __ shift_left(index, shift, tmp); index = tmp; } - if (disp != 0) { + if (large_disp != 0) { LIR_Opr tmp = new_pointer_register(); - if (Assembler::is_simm13(disp)) { - __ add(tmp, LIR_OprFact::intptrConst(disp), tmp); + if (Assembler::is_simm13(large_disp)) { + __ add(tmp, LIR_OprFact::intptrConst(large_disp), tmp); index = tmp; } else { - __ move(LIR_OprFact::intptrConst(disp), tmp); + __ move(LIR_OprFact::intptrConst(large_disp), tmp); __ add(tmp, index, tmp); index = tmp; } - disp = 0; + large_disp = 0; } - } else if (disp != 0 && !Assembler::is_simm13(disp)) { + } else if (large_disp != 0 && !Assembler::is_simm13(large_disp)) { // index is illegal so replace it with the displacement loaded into a register index = new_pointer_register(); - __ move(LIR_OprFact::intptrConst(disp), index); - disp = 0; + __ move(LIR_OprFact::intptrConst(large_disp), index); + large_disp = 0; } // at this point we either have base + index or base + displacement - if (disp == 0) { + if (large_disp == 0) { return new LIR_Address(base, index, type); } else { - assert(Assembler::is_simm13(disp), "must be"); - return new LIR_Address(base, disp, type); + assert(Assembler::is_simm13(large_disp), "must be"); + return new LIR_Address(base, large_disp, type); } } @@ -196,11 +197,11 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o int shift = exact_log2(elem_size); LIR_Opr base_opr; - int offset = arrayOopDesc::base_offset_in_bytes(type); + intx offset = arrayOopDesc::base_offset_in_bytes(type); if (index_opr->is_constant()) { - int i = index_opr->as_constant_ptr()->as_jint(); - int array_offset = i * elem_size; + intx i = index_opr->as_constant_ptr()->as_jint(); + intx array_offset = i * elem_size; if (Assembler::is_simm13(array_offset + offset)) { base_opr = array_opr; offset = array_offset + offset; @@ -953,6 +954,10 @@ void LIRGenerator::do_update_CRC32C(Intrinsic* x) { } } +void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { + fatal("FMA intrinsic is not implemented on this platform"); +} + void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { fatal("vectorizedMismatch intrinsic is not implemented on this platform"); } diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp index 283f260886d..5530a85cb4c 100644 --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @@ -881,20 +881,15 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ delayed()->st_ptr(tmp, G2_thread, satb_q_index_byte_offset); __ bind(refill); - __ save_frame(0); - __ mov(pre_val, L0); - __ mov(tmp, L1); - __ mov(tmp2, L2); + save_live_registers(sasm); __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SATBMarkQueueSet::handle_zero_index_for_thread), G2_thread); - __ mov(L0, pre_val); - __ mov(L1, tmp); - __ mov(L2, tmp2); + restore_live_registers(sasm); __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); __ delayed()->restore(); @@ -986,20 +981,15 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { __ delayed()->st_ptr(tmp3, G2_thread, dirty_card_q_index_byte_offset); __ bind(refill); - __ save_frame(0); - __ mov(tmp2, L0); - __ mov(tmp3, L1); - __ mov(tmp4, L2); + save_live_registers(sasm); __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, DirtyCardQueueSet::handle_zero_index_for_thread), G2_thread); - __ mov(L0, tmp2); - __ mov(L1, tmp3); - __ mov(L2, tmp4); + restore_live_registers(sasm); __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); __ delayed()->restore(); diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 88ac31e096d..8f68d1112f2 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -266,6 +266,11 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseGHASHIntrinsics, false); } + if (UseFMA) { + warning("FMA instructions are not available on this CPU"); + FLAG_SET_DEFAULT(UseFMA, false); + } + // SHA1, SHA256, and SHA512 instructions were added to SPARC T-series at different times if (has_sha1() || has_sha256() || has_sha512()) { if (UseVIS > 0) { // SHA intrinsics use VIS1 instructions diff --git a/hotspot/src/cpu/x86/vm/abstractInterpreter_x86.cpp b/hotspot/src/cpu/x86/vm/abstractInterpreter_x86.cpp index 5a1f37f26a7..0865b99a0d6 100644 --- a/hotspot/src/cpu/x86/vm/abstractInterpreter_x86.cpp +++ b/hotspot/src/cpu/x86/vm/abstractInterpreter_x86.cpp @@ -172,7 +172,9 @@ bool AbstractInterpreter::can_be_compiled(methodHandle m) { case Interpreter::java_lang_math_log10 : // fall thru case Interpreter::java_lang_math_sqrt : // fall thru case Interpreter::java_lang_math_pow : // fall thru - case Interpreter::java_lang_math_exp : + case Interpreter::java_lang_math_exp : // fall thru + case Interpreter::java_lang_math_fmaD : // fall thru + case Interpreter::java_lang_math_fmaF : return false; default: return true; diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index 94f37e4d4b4..d00802e2708 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -4769,6 +4769,22 @@ void Assembler::vdivss(XMMRegister dst, XMMRegister nds, XMMRegister src) { emit_int8((unsigned char)(0xC0 | encode)); } +void Assembler::vfmadd231sd(XMMRegister dst, XMMRegister src1, XMMRegister src2) { + assert(VM_Version::supports_fma(), ""); + InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = vex_prefix_and_encode(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xB9); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::vfmadd231ss(XMMRegister dst, XMMRegister src1, XMMRegister src2) { + assert(VM_Version::supports_fma(), ""); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = vex_prefix_and_encode(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xB9); + emit_int8((unsigned char)(0xC0 | encode)); +} + void Assembler::vmulsd(XMMRegister dst, XMMRegister nds, Address src) { assert(VM_Version::supports_avx(), ""); InstructionMark im(this); diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index 5911b8368c2..f787ec5533a 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -1860,6 +1860,8 @@ private: void vdivsd(XMMRegister dst, XMMRegister nds, XMMRegister src); void vdivss(XMMRegister dst, XMMRegister nds, Address src); void vdivss(XMMRegister dst, XMMRegister nds, XMMRegister src); + void vfmadd231sd(XMMRegister dst, XMMRegister nds, XMMRegister src); + void vfmadd231ss(XMMRegister dst, XMMRegister nds, XMMRegister src); void vmulsd(XMMRegister dst, XMMRegister nds, Address src); void vmulsd(XMMRegister dst, XMMRegister nds, XMMRegister src); void vmulss(XMMRegister dst, XMMRegister nds, Address src); diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 3a9bf0a6d2f..3adff833033 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -1345,6 +1345,18 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) { op->result_opr(), op->info()); break; + case lir_fmad: + __ fmad(op->result_opr()->as_xmm_double_reg(), + op->in_opr1()->as_xmm_double_reg(), + op->in_opr2()->as_xmm_double_reg(), + op->in_opr3()->as_xmm_double_reg()); + break; + case lir_fmaf: + __ fmaf(op->result_opr()->as_xmm_float_reg(), + op->in_opr1()->as_xmm_float_reg(), + op->in_opr2()->as_xmm_float_reg(), + op->in_opr3()->as_xmm_float_reg()); + break; default: ShouldNotReachHere(); break; } } diff --git a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp index 43e98a7d43f..c5bec4b7e0b 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp @@ -152,7 +152,7 @@ LIR_Address* LIRGenerator::generate_address(LIR_Opr base, LIR_Opr index, assert(base->is_register(), "must be"); if (index->is_constant()) { return new LIR_Address(base, - (index->as_constant_ptr()->as_jint() << shift) + disp, + ((intx)(index->as_constant_ptr()->as_jint()) << shift) + disp, type); } else { return new LIR_Address(base, index, (LIR_Address::Scale)shift, disp, type); @@ -168,7 +168,7 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o if (index_opr->is_constant()) { int elem_size = type2aelembytes(type); addr = new LIR_Address(array_opr, - offset_in_bytes + index_opr->as_jint() * elem_size, type); + offset_in_bytes + (intx)(index_opr->as_jint()) * elem_size, type); } else { #ifdef _LP64 if (index_opr->type() == T_INT) { @@ -806,6 +806,32 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) { } } +void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { + assert(x->number_of_arguments() == 3, "wrong type"); + assert(UseFMA, "Needs FMA instructions support."); + LIRItem value(x->argument_at(0), this); + LIRItem value1(x->argument_at(1), this); + LIRItem value2(x->argument_at(2), this); + + value2.set_destroys_register(); + + value.load_item(); + value1.load_item(); + value2.load_item(); + + LIR_Opr calc_input = value.result(); + LIR_Opr calc_input1 = value1.result(); + LIR_Opr calc_input2 = value2.result(); + LIR_Opr calc_result = rlock_result(x); + + switch (x->id()) { + case vmIntrinsics::_fmaD: __ fmad(calc_input, calc_input1, calc_input2, calc_result); break; + case vmIntrinsics::_fmaF: __ fmaf(calc_input, calc_input1, calc_input2, calc_result); break; + default: ShouldNotReachHere(); + } + +} + void LIRGenerator::do_MathIntrinsic(Intrinsic* x) { assert(x->number_of_arguments() == 1 || (x->number_of_arguments() == 2 && x->id() == vmIntrinsics::_dpow), "wrong type"); diff --git a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp index a5e533696b2..6d0dbb8756d 100644 --- a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp @@ -100,9 +100,11 @@ inline void LinearScan::pd_add_temps(LIR_Op* op) { inline bool LinearScanWalker::pd_init_regs_for_alloc(Interval* cur) { int last_xmm_reg = pd_last_xmm_reg; +#ifdef _LP64 if (UseAVX < 3) { last_xmm_reg = pd_first_xmm_reg + (pd_nof_xmm_regs_frame_map / 2) - 1; } +#endif if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::byte_reg)) { assert(cur->type() != T_FLOAT && cur->type() != T_DOUBLE, "cpu regs only"); _first_reg = pd_first_byte_reg; diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index 8ec00bd9fce..150cf6d8301 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -3147,6 +3147,24 @@ void MacroAssembler::fremr(Register tmp) { fpop(); } +// dst = c = a * b + c +void MacroAssembler::fmad(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c) { + Assembler::vfmadd231sd(c, a, b); + if (dst != c) { + movdbl(dst, c); + } +} + +// dst = c = a * b + c +void MacroAssembler::fmaf(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c) { + Assembler::vfmadd231ss(c, a, b); + if (dst != c) { + movflt(dst, c); + } +} + + + void MacroAssembler::incrementl(AddressLiteral dst) { if (reachable(dst)) { diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp index cd3c67c4ab2..382b0011882 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -449,6 +449,10 @@ class MacroAssembler: public Assembler { // tmp is a temporary register, if none is available use noreg void fremr(Register tmp); + // dst = c = a * b + c + void fmad(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c); + void fmaf(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c); + // same as fcmp2int, but using SSE2 void cmpss2int(XMMRegister opr1, XMMRegister opr2, Register dst, bool unordered_is_less); diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp index a0910f395bb..b8af7c33158 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp @@ -720,19 +720,13 @@ const Register& y2 = r15; enum { _XFER_SIZE = 2*64*4, // 2 blocks, 64 rounds, 4 bytes/round -#ifndef _WIN64 - _XMM_SAVE_SIZE = 0, -#else - _XMM_SAVE_SIZE = 8*16, -#endif _INP_END_SIZE = 8, _INP_SIZE = 8, _CTX_SIZE = 8, _RSP_SIZE = 8, _XFER = 0, - _XMM_SAVE = _XFER + _XFER_SIZE, - _INP_END = _XMM_SAVE + _XMM_SAVE_SIZE, + _INP_END = _XFER + _XFER_SIZE, _INP = _INP_END + _INP_END_SIZE, _CTX = _INP + _INP_SIZE, _RSP = _CTX + _CTX_SIZE, diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 668b3e1e128..4906f9dc89f 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -3236,11 +3236,6 @@ class StubGenerator: public StubCodeGenerator { #ifdef _WIN64 // on win64, fill len_reg from stack position __ movl(len_reg, len_mem); - // save the xmm registers which must be preserved 6-15 - __ subptr(rsp, -rsp_after_call_off * wordSize); - for (int i = 6; i <= XMM_REG_NUM_KEY_LAST; i++) { - __ movdqu(xmm_save(i), as_XMMRegister(i)); - } #else __ push(len_reg); // Save #endif @@ -3281,10 +3276,6 @@ class StubGenerator: public StubCodeGenerator { __ movdqu(Address(rvec, 0), xmm_result); // final value of r stored in rvec of CipherBlockChaining object #ifdef _WIN64 - // restore xmm regs belonging to calling function - for (int i = 6; i <= XMM_REG_NUM_KEY_LAST; i++) { - __ movdqu(as_XMMRegister(i), xmm_save(i)); - } __ movl(rax, len_mem); #else __ pop(rax); // return length @@ -3446,11 +3437,6 @@ class StubGenerator: public StubCodeGenerator { #ifdef _WIN64 // on win64, fill len_reg from stack position __ movl(len_reg, len_mem); - // save the xmm registers which must be preserved 6-15 - __ subptr(rsp, -rsp_after_call_off * wordSize); - for (int i = 6; i <= XMM_REG_NUM_KEY_LAST; i++) { - __ movdqu(xmm_save(i), as_XMMRegister(i)); - } #else __ push(len_reg); // Save #endif @@ -3644,10 +3630,6 @@ class StubGenerator: public StubCodeGenerator { __ movdqu(Address(rvec, 0), xmm_prev_block_cipher); // final value of r stored in rvec of CipherBlockChaining object __ pop(rbx); #ifdef _WIN64 - // restore regs belonging to calling function - for (int i = 6; i <= XMM_REG_NUM_KEY_LAST; i++) { - __ movdqu(as_XMMRegister(i), xmm_save(i)); - } __ movl(rax, len_mem); #else __ pop(rax); // return length @@ -3699,25 +3681,12 @@ class StubGenerator: public StubCodeGenerator { __ enter(); -#ifdef _WIN64 - // save the xmm registers which must be preserved 6-7 - __ subptr(rsp, 4 * wordSize); - __ movdqu(Address(rsp, 0), xmm6); - __ movdqu(Address(rsp, 2 * wordSize), xmm7); -#endif - __ subptr(rsp, 4 * wordSize); __ fast_sha1(abcd, e0, e1, msg0, msg1, msg2, msg3, shuf_mask, buf, state, ofs, limit, rsp, multi_block); __ addptr(rsp, 4 * wordSize); -#ifdef _WIN64 - // restore xmm regs belonging to calling function - __ movdqu(xmm6, Address(rsp, 0)); - __ movdqu(xmm7, Address(rsp, 2 * wordSize)); - __ addptr(rsp, 4 * wordSize); -#endif __ leave(); __ ret(0); @@ -3775,22 +3744,6 @@ class StubGenerator: public StubCodeGenerator { const XMMRegister shuf_mask = xmm8; __ enter(); -#ifdef _WIN64 - // save the xmm registers which must be preserved 6-7 - __ subptr(rsp, 6 * wordSize); - __ movdqu(Address(rsp, 0), xmm6); - __ movdqu(Address(rsp, 2 * wordSize), xmm7); - __ movdqu(Address(rsp, 4 * wordSize), xmm8); - - if (!VM_Version::supports_sha() && VM_Version::supports_avx2()) { - __ subptr(rsp, 10 * wordSize); - __ movdqu(Address(rsp, 0), xmm9); - __ movdqu(Address(rsp, 2 * wordSize), xmm10); - __ movdqu(Address(rsp, 4 * wordSize), xmm11); - __ movdqu(Address(rsp, 6 * wordSize), xmm12); - __ movdqu(Address(rsp, 8 * wordSize), xmm13); - } -#endif __ subptr(rsp, 4 * wordSize); @@ -3802,21 +3755,7 @@ class StubGenerator: public StubCodeGenerator { buf, state, ofs, limit, rsp, multi_block, shuf_mask); } __ addptr(rsp, 4 * wordSize); -#ifdef _WIN64 - // restore xmm regs belonging to calling function - if (!VM_Version::supports_sha() && VM_Version::supports_avx2()) { - __ movdqu(xmm9, Address(rsp, 0)); - __ movdqu(xmm10, Address(rsp, 2 * wordSize)); - __ movdqu(xmm11, Address(rsp, 4 * wordSize)); - __ movdqu(xmm12, Address(rsp, 6 * wordSize)); - __ movdqu(xmm13, Address(rsp, 8 * wordSize)); - __ addptr(rsp, 10 * wordSize); - } - __ movdqu(xmm6, Address(rsp, 0)); - __ movdqu(xmm7, Address(rsp, 2 * wordSize)); - __ movdqu(xmm8, Address(rsp, 4 * wordSize)); - __ addptr(rsp, 6 * wordSize); -#endif + __ leave(); __ ret(0); return start; @@ -3917,18 +3856,14 @@ class StubGenerator: public StubCodeGenerator { } #ifdef _WIN64 - // save the xmm registers which must be preserved 6-14 - const int XMM_REG_NUM_KEY_LAST = 14; - __ subptr(rsp, -rsp_after_call_off * wordSize); - for (int i = 6; i <= XMM_REG_NUM_KEY_LAST; i++) { - __ movdqu(xmm_save(i), as_XMMRegister(i)); - } - - const Address r13_save(rbp, rdi_off * wordSize); - const Address r14_save(rbp, rsi_off * wordSize); - - __ movptr(r13_save, r13); - __ movptr(r14_save, r14); + // allocate spill slots for r13, r14 + enum { + saved_r13_offset, + saved_r14_offset + }; + __ subptr(rsp, 2 * wordSize); + __ movptr(Address(rsp, saved_r13_offset * wordSize), r13); + __ movptr(Address(rsp, saved_r14_offset * wordSize), r14); // on win64, fill len_reg from stack position __ movl(len_reg, len_mem); @@ -4130,13 +4065,10 @@ class StubGenerator: public StubCodeGenerator { __ movdqu(Address(counter, 0), xmm_curr_counter); //save counter back __ pop(rbx); // pop the saved RBX. #ifdef _WIN64 - // restore regs belonging to calling function - for (int i = 6; i <= XMM_REG_NUM_KEY_LAST; i++) { - __ movdqu(as_XMMRegister(i), xmm_save(i)); - } __ movl(rax, len_mem); - __ movptr(r13, r13_save); - __ movptr(r14, r14_save); + __ movptr(r13, Address(rsp, saved_r13_offset * wordSize)); + __ movptr(r14, Address(rsp, saved_r14_offset * wordSize)); + __ addptr(rsp, 2 * wordSize); #else __ pop(rax); // return 'len' #endif @@ -4177,10 +4109,6 @@ class StubGenerator: public StubCodeGenerator { const Register data = c_rarg2; const Register blocks = c_rarg3; -#ifdef _WIN64 - const int XMM_REG_LAST = 10; -#endif - const XMMRegister xmm_temp0 = xmm0; const XMMRegister xmm_temp1 = xmm1; const XMMRegister xmm_temp2 = xmm2; @@ -4203,14 +4131,6 @@ class StubGenerator: public StubCodeGenerator { __ kmovql(k1, rax); } -#ifdef _WIN64 - // save the xmm registers which must be preserved 6-10 - __ subptr(rsp, -rsp_after_call_off * wordSize); - for (int i = 6; i <= XMM_REG_LAST; i++) { - __ movdqu(xmm_save(i), as_XMMRegister(i)); - } -#endif - __ movdqu(xmm_temp10, ExternalAddress(StubRoutines::x86::ghash_long_swap_mask_addr())); __ movdqu(xmm_temp0, Address(state, 0)); @@ -4310,12 +4230,6 @@ class StubGenerator: public StubCodeGenerator { __ pshufb(xmm_temp6, xmm_temp10); // Byte swap 16-byte result __ movdqu(Address(state, 0), xmm_temp6); // store the result -#ifdef _WIN64 - // restore xmm regs belonging to calling function - for (int i = 6; i <= XMM_REG_LAST; i++) { - __ movdqu(as_XMMRegister(i), xmm_save(i)); - } -#endif __ leave(); __ ret(0); return start; @@ -4652,21 +4566,8 @@ class StubGenerator: public StubCodeGenerator { BLOCK_COMMENT("Entry:"); __ enter(); // required for proper stackwalking of RuntimeStub frame -#ifdef _WIN64 - // save the xmm registers which must be preserved 6-7 - __ subptr(rsp, 4 * wordSize); - __ movdqu(Address(rsp, 0), xmm6); - __ movdqu(Address(rsp, 2 * wordSize), xmm7); -#endif __ fast_exp(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp); -#ifdef _WIN64 - // restore xmm regs belonging to calling function - __ movdqu(xmm6, Address(rsp, 0)); - __ movdqu(xmm7, Address(rsp, 2 * wordSize)); - __ addptr(rsp, 4 * wordSize); -#endif - __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -4693,21 +4594,8 @@ class StubGenerator: public StubCodeGenerator { BLOCK_COMMENT("Entry:"); __ enter(); // required for proper stackwalking of RuntimeStub frame -#ifdef _WIN64 - // save the xmm registers which must be preserved 6-7 - __ subptr(rsp, 4 * wordSize); - __ movdqu(Address(rsp, 0), xmm6); - __ movdqu(Address(rsp, 2 * wordSize), xmm7); -#endif __ fast_log(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp1, tmp2); -#ifdef _WIN64 - // restore xmm regs belonging to calling function - __ movdqu(xmm6, Address(rsp, 0)); - __ movdqu(xmm7, Address(rsp, 2 * wordSize)); - __ addptr(rsp, 4 * wordSize); -#endif - __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -4733,21 +4621,8 @@ class StubGenerator: public StubCodeGenerator { BLOCK_COMMENT("Entry:"); __ enter(); // required for proper stackwalking of RuntimeStub frame -#ifdef _WIN64 - // save the xmm registers which must be preserved 6-7 - __ subptr(rsp, 4 * wordSize); - __ movdqu(Address(rsp, 0), xmm6); - __ movdqu(Address(rsp, 2 * wordSize), xmm7); -#endif __ fast_log10(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp); -#ifdef _WIN64 - // restore xmm regs belonging to calling function - __ movdqu(xmm6, Address(rsp, 0)); - __ movdqu(xmm7, Address(rsp, 2 * wordSize)); - __ addptr(rsp, 4 * wordSize); -#endif - __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -4776,21 +4651,8 @@ class StubGenerator: public StubCodeGenerator { BLOCK_COMMENT("Entry:"); __ enter(); // required for proper stackwalking of RuntimeStub frame -#ifdef _WIN64 - // save the xmm registers which must be preserved 6-7 - __ subptr(rsp, 4 * wordSize); - __ movdqu(Address(rsp, 0), xmm6); - __ movdqu(Address(rsp, 2 * wordSize), xmm7); -#endif __ fast_pow(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp1, tmp2, tmp3, tmp4); -#ifdef _WIN64 - // restore xmm regs belonging to calling function - __ movdqu(xmm6, Address(rsp, 0)); - __ movdqu(xmm7, Address(rsp, 2 * wordSize)); - __ addptr(rsp, 4 * wordSize); -#endif - __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -4822,18 +4684,10 @@ class StubGenerator: public StubCodeGenerator { #ifdef _WIN64 __ push(rsi); __ push(rdi); - // save the xmm registers which must be preserved 6-7 - __ subptr(rsp, 4 * wordSize); - __ movdqu(Address(rsp, 0), xmm6); - __ movdqu(Address(rsp, 2 * wordSize), xmm7); #endif __ fast_sin(x0, x1, x2, x3, x4, x5, x6, x7, rax, rbx, rcx, rdx, tmp1, tmp2, tmp3, tmp4); #ifdef _WIN64 - // restore xmm regs belonging to calling function - __ movdqu(xmm6, Address(rsp, 0)); - __ movdqu(xmm7, Address(rsp, 2 * wordSize)); - __ addptr(rsp, 4 * wordSize); __ pop(rdi); __ pop(rsi); #endif @@ -4869,18 +4723,10 @@ class StubGenerator: public StubCodeGenerator { #ifdef _WIN64 __ push(rsi); __ push(rdi); - // save the xmm registers which must be preserved 6-7 - __ subptr(rsp, 4 * wordSize); - __ movdqu(Address(rsp, 0), xmm6); - __ movdqu(Address(rsp, 2 * wordSize), xmm7); #endif __ fast_cos(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp1, tmp2, tmp3, tmp4); #ifdef _WIN64 - // restore xmm regs belonging to calling function - __ movdqu(xmm6, Address(rsp, 0)); - __ movdqu(xmm7, Address(rsp, 2 * wordSize)); - __ addptr(rsp, 4 * wordSize); __ pop(rdi); __ pop(rsi); #endif @@ -4916,18 +4762,10 @@ class StubGenerator: public StubCodeGenerator { #ifdef _WIN64 __ push(rsi); __ push(rdi); - // save the xmm registers which must be preserved 6-7 - __ subptr(rsp, 4 * wordSize); - __ movdqu(Address(rsp, 0), xmm6); - __ movdqu(Address(rsp, 2 * wordSize), xmm7); #endif __ fast_tan(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp1, tmp2, tmp3, tmp4); #ifdef _WIN64 - // restore xmm regs belonging to calling function - __ movdqu(xmm6, Address(rsp, 0)); - __ movdqu(xmm7, Address(rsp, 2 * wordSize)); - __ addptr(rsp, 4 * wordSize); __ pop(rdi); __ pop(rsi); #endif diff --git a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp index 6441d19cf5f..dd978fd1020 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp @@ -55,7 +55,7 @@ // Run with +PrintInterpreter to get the VM to print out the size. // Max size with JVMTI #ifdef AMD64 -int TemplateInterpreter::InterpreterCodeSize = 256 * 1024; +int TemplateInterpreter::InterpreterCodeSize = JVMCI_ONLY(268) NOT_JVMCI(256) * 1024; #else int TemplateInterpreter::InterpreterCodeSize = 224 * 1024; #endif // AMD64 diff --git a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86_32.cpp index 77cd5249d84..98b52c7cf1b 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86_32.cpp @@ -341,6 +341,27 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M // [ lo(arg) ] // [ hi(arg) ] // + if (kind == Interpreter::java_lang_math_fmaD) { + __ movdbl(xmm2, Address(rsp, 5 * wordSize)); + __ movdbl(xmm1, Address(rsp, 3 * wordSize)); + __ movdbl(xmm0, Address(rsp, 1 * wordSize)); + __ fmad(xmm0, xmm1, xmm2, xmm0); + __ pop(rdi); // get return address + __ mov(rsp, rsi); // set sp to sender sp + __ jmp(rdi); + + return entry_point; + } else if (kind == Interpreter::java_lang_math_fmaF) { + __ movflt(xmm2, Address(rsp, 3 * wordSize)); + __ movflt(xmm1, Address(rsp, 2 * wordSize)); + __ movflt(xmm0, Address(rsp, 1 * wordSize)); + __ fmaf(xmm0, xmm1, xmm2, xmm0); + __ pop(rdi); // get return address + __ mov(rsp, rsi); // set sp to sender sp + __ jmp(rdi); + + return entry_point; + } __ fld_d(Address(rsp, 1*wordSize)); switch (kind) { diff --git a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86_64.cpp index ed412203a4a..6cdf3c64cfd 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86_64.cpp @@ -369,8 +369,17 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M // [ hi(arg) ] // - - if (kind == Interpreter::java_lang_math_sqrt) { + if (kind == Interpreter::java_lang_math_fmaD) { + __ movdbl(xmm0, Address(rsp, wordSize)); + __ movdbl(xmm1, Address(rsp, 3 * wordSize)); + __ movdbl(xmm2, Address(rsp, 5 * wordSize)); + __ fmad(xmm0, xmm1, xmm2, xmm0); + } else if (kind == Interpreter::java_lang_math_fmaF) { + __ movflt(xmm0, Address(rsp, wordSize)); + __ movflt(xmm1, Address(rsp, 2 * wordSize)); + __ movflt(xmm2, Address(rsp, 3 * wordSize)); + __ fmaf(xmm0, xmm1, xmm2, xmm0); + } else if (kind == Interpreter::java_lang_math_sqrt) { __ sqrtsd(xmm0, Address(rsp, wordSize)); } else if (kind == Interpreter::java_lang_math_exp) { __ movdbl(xmm0, Address(rsp, wordSize)); diff --git a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp index 713ee14472d..0307107ad9b 100644 --- a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp @@ -73,6 +73,7 @@ #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ declare_preprocessor_constant("VM_Version::CPU_AVX512BW", CPU_AVX512BW) \ declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) \ - declare_preprocessor_constant("VM_Version::CPU_SHA", CPU_SHA) + declare_preprocessor_constant("VM_Version::CPU_SHA", CPU_SHA) \ + declare_preprocessor_constant("VM_Version::CPU_FMA", CPU_FMA) #endif // CPU_X86_VM_VMSTRUCTS_X86_HPP diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index ef78e640fd8..aa10ef276f2 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -578,7 +578,7 @@ void VM_Version::get_processor_features() { } char buf[256]; - jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", cores_per_cpu(), threads_per_core(), cpu_family(), _model, _stepping, (supports_cmov() ? ", cmov" : ""), @@ -610,7 +610,8 @@ void VM_Version::get_processor_features() { (supports_bmi2() ? ", bmi2" : ""), (supports_adx() ? ", adx" : ""), (supports_evex() ? ", evex" : ""), - (supports_sha() ? ", sha" : "")); + (supports_sha() ? ", sha" : ""), + (supports_fma() ? ", fma" : "")); _features_string = os::strdup(buf); // UseSSE is set to the smaller of what hardware supports and what @@ -732,6 +733,15 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseGHASHIntrinsics, false); } + if (supports_fma() && UseSSE >= 2) { + if (FLAG_IS_DEFAULT(UseFMA)) { + UseFMA = true; + } + } else if (UseFMA) { + warning("FMA instructions are not available on this CPU"); + FLAG_SET_DEFAULT(UseFMA, false); + } + if (supports_sha() LP64_ONLY(|| supports_avx2() && supports_bmi2())) { if (FLAG_IS_DEFAULT(UseSHA)) { UseSHA = true; @@ -773,7 +783,6 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); } - // Adjust RTM (Restricted Transactional Memory) flags if (!supports_rtm() && UseRTMLocking) { // Can't continue because UseRTMLocking affects UseBiasedLocking flag // setting during arguments processing. See use_biased_locking(). diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp index a4c02654cad..5a51889e06b 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp @@ -74,7 +74,8 @@ class VM_Version : public Abstract_VM_Version { : 1, ssse3 : 1, cid : 1, - : 2, + : 1, + fma : 1, cmpxchg16: 1, : 4, dca : 1, @@ -289,6 +290,7 @@ protected: #define CPU_AVX512BW ((uint64_t)UCONST64(0x100000000)) // enums are limited to 31 bit #define CPU_AVX512VL ((uint64_t)UCONST64(0x200000000)) // EVEX instructions with smaller vector length #define CPU_SHA ((uint64_t)UCONST64(0x400000000)) // SHA instructions +#define CPU_FMA ((uint64_t)UCONST64(0x800000000)) // FMA instructions enum Extended_Family { // AMD @@ -522,6 +524,8 @@ protected: result |= CPU_SHA; if(_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0) result |= CPU_LZCNT; + if (_cpuid_info.std_cpuid1_ecx.bits.fma != 0) + result |= CPU_FMA; // for Intel, ecx.bits.misalignsse bit (bit 8) indicates support for prefetchw if (_cpuid_info.ext_cpuid1_ecx.bits.misalignsse != 0) { result |= CPU_3DNOW_PREFETCH; @@ -726,6 +730,7 @@ public: static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); } static bool supports_avxonly() { return ((supports_avx2() || supports_avx()) && !supports_evex()); } static bool supports_sha() { return (_features & CPU_SHA) != 0; } + static bool supports_fma() { return (_features & CPU_FMA) != 0; } // Intel features static bool is_intel_family_core() { return is_intel() && extended_cpu_family() == CPU_FAMILY_INTEL_CORE; } diff --git a/hotspot/src/cpu/x86/vm/x86.ad b/hotspot/src/cpu/x86/vm/x86.ad index b12c979996b..24eab7f3785 100644 --- a/hotspot/src/cpu/x86/vm/x86.ad +++ b/hotspot/src/cpu/x86/vm/x86.ad @@ -176,451 +176,6 @@ reg_def XMM5n( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next(13)); reg_def XMM5o( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next(14)); reg_def XMM5p( SOC, SOC, Op_RegF, 5, xmm5->as_VMReg()->next(15)); -#ifdef _WIN64 - -reg_def XMM6 ( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()); -reg_def XMM6b( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(1)); -reg_def XMM6c( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(2)); -reg_def XMM6d( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(3)); -reg_def XMM6e( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(4)); -reg_def XMM6f( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(5)); -reg_def XMM6g( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(6)); -reg_def XMM6h( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(7)); -reg_def XMM6i( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(8)); -reg_def XMM6j( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(9)); -reg_def XMM6k( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(10)); -reg_def XMM6l( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(11)); -reg_def XMM6m( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(12)); -reg_def XMM6n( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(13)); -reg_def XMM6o( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(14)); -reg_def XMM6p( SOC, SOE, Op_RegF, 6, xmm6->as_VMReg()->next(15)); - -reg_def XMM7 ( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()); -reg_def XMM7b( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(1)); -reg_def XMM7c( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(2)); -reg_def XMM7d( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(3)); -reg_def XMM7e( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(4)); -reg_def XMM7f( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(5)); -reg_def XMM7g( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(6)); -reg_def XMM7h( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(7)); -reg_def XMM7i( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(8)); -reg_def XMM7j( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(9)); -reg_def XMM7k( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(10)); -reg_def XMM7l( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(11)); -reg_def XMM7m( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(12)); -reg_def XMM7n( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(13)); -reg_def XMM7o( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(14)); -reg_def XMM7p( SOC, SOE, Op_RegF, 7, xmm7->as_VMReg()->next(15)); - -reg_def XMM8 ( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()); -reg_def XMM8b( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(1)); -reg_def XMM8c( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(2)); -reg_def XMM8d( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(3)); -reg_def XMM8e( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(4)); -reg_def XMM8f( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(5)); -reg_def XMM8g( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(6)); -reg_def XMM8h( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(7)); -reg_def XMM8i( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(8)); -reg_def XMM8j( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(9)); -reg_def XMM8k( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(10)); -reg_def XMM8l( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(11)); -reg_def XMM8m( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(12)); -reg_def XMM8n( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(13)); -reg_def XMM8o( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(14)); -reg_def XMM8p( SOC, SOE, Op_RegF, 8, xmm8->as_VMReg()->next(15)); - -reg_def XMM9 ( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()); -reg_def XMM9b( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(1)); -reg_def XMM9c( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(2)); -reg_def XMM9d( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(3)); -reg_def XMM9e( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(4)); -reg_def XMM9f( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(5)); -reg_def XMM9g( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(6)); -reg_def XMM9h( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(7)); -reg_def XMM9i( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(8)); -reg_def XMM9j( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(9)); -reg_def XMM9k( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(10)); -reg_def XMM9l( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(11)); -reg_def XMM9m( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(12)); -reg_def XMM9n( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(13)); -reg_def XMM9o( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(14)); -reg_def XMM9p( SOC, SOE, Op_RegF, 9, xmm9->as_VMReg()->next(15)); - -reg_def XMM10 ( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()); -reg_def XMM10b( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(1)); -reg_def XMM10c( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(2)); -reg_def XMM10d( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(3)); -reg_def XMM10e( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(4)); -reg_def XMM10f( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(5)); -reg_def XMM10g( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(6)); -reg_def XMM10h( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(7)); -reg_def XMM10i( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(8)); -reg_def XMM10j( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(9)); -reg_def XMM10k( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(10)); -reg_def XMM10l( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(11)); -reg_def XMM10m( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(12)); -reg_def XMM10n( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(13)); -reg_def XMM10o( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(14)); -reg_def XMM10p( SOC, SOE, Op_RegF, 10, xmm10->as_VMReg()->next(15)); - -reg_def XMM11 ( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()); -reg_def XMM11b( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(1)); -reg_def XMM11c( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(2)); -reg_def XMM11d( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(3)); -reg_def XMM11e( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(4)); -reg_def XMM11f( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(5)); -reg_def XMM11g( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(6)); -reg_def XMM11h( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(7)); -reg_def XMM11i( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(8)); -reg_def XMM11j( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(9)); -reg_def XMM11k( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(10)); -reg_def XMM11l( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(11)); -reg_def XMM11m( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(12)); -reg_def XMM11n( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(13)); -reg_def XMM11o( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(14)); -reg_def XMM11p( SOC, SOE, Op_RegF, 11, xmm11->as_VMReg()->next(15)); - -reg_def XMM12 ( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()); -reg_def XMM12b( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(1)); -reg_def XMM12c( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(2)); -reg_def XMM12d( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(3)); -reg_def XMM12e( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(4)); -reg_def XMM12f( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(5)); -reg_def XMM12g( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(6)); -reg_def XMM12h( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(7)); -reg_def XMM12i( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(8)); -reg_def XMM12j( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(9)); -reg_def XMM12k( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(10)); -reg_def XMM12l( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(11)); -reg_def XMM12m( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(12)); -reg_def XMM12n( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(13)); -reg_def XMM12o( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(14)); -reg_def XMM12p( SOC, SOE, Op_RegF, 12, xmm12->as_VMReg()->next(15)); - -reg_def XMM13 ( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()); -reg_def XMM13b( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(1)); -reg_def XMM13c( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(2)); -reg_def XMM13d( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(3)); -reg_def XMM13e( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(4)); -reg_def XMM13f( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(5)); -reg_def XMM13g( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(6)); -reg_def XMM13h( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(7)); -reg_def XMM13i( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(8)); -reg_def XMM13j( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(9)); -reg_def XMM13k( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(10)); -reg_def XMM13l( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(11)); -reg_def XMM13m( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(12)); -reg_def XMM13n( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(13)); -reg_def XMM13o( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(14)); -reg_def XMM13p( SOC, SOE, Op_RegF, 13, xmm13->as_VMReg()->next(15)); - -reg_def XMM14 ( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()); -reg_def XMM14b( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(1)); -reg_def XMM14c( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(2)); -reg_def XMM14d( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(3)); -reg_def XMM14e( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(4)); -reg_def XMM14f( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(5)); -reg_def XMM14g( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(6)); -reg_def XMM14h( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(7)); -reg_def XMM14i( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(8)); -reg_def XMM14j( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(9)); -reg_def XMM14k( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(10)); -reg_def XMM14l( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(11)); -reg_def XMM14m( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(12)); -reg_def XMM14n( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(13)); -reg_def XMM14o( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(14)); -reg_def XMM14p( SOC, SOE, Op_RegF, 14, xmm14->as_VMReg()->next(15)); - -reg_def XMM15 ( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()); -reg_def XMM15b( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(1)); -reg_def XMM15c( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(2)); -reg_def XMM15d( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(3)); -reg_def XMM15e( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(4)); -reg_def XMM15f( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(5)); -reg_def XMM15g( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(6)); -reg_def XMM15h( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(7)); -reg_def XMM15i( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(8)); -reg_def XMM15j( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(9)); -reg_def XMM15k( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(10)); -reg_def XMM15l( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(11)); -reg_def XMM15m( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(12)); -reg_def XMM15n( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(13)); -reg_def XMM15o( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(14)); -reg_def XMM15p( SOC, SOE, Op_RegF, 15, xmm15->as_VMReg()->next(15)); - -reg_def XMM16 ( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()); -reg_def XMM16b( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()->next(1)); -reg_def XMM16c( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()->next(2)); -reg_def XMM16d( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()->next(3)); -reg_def XMM16e( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()->next(4)); -reg_def XMM16f( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()->next(5)); -reg_def XMM16g( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()->next(6)); -reg_def XMM16h( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()->next(7)); -reg_def XMM16i( SOC, SOE, Op_RegF, 16, xmm15->as_VMReg()->next(8)); -reg_def XMM16j( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()->next(9)); -reg_def XMM16k( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()->next(10)); -reg_def XMM16l( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()->next(11)); -reg_def XMM16m( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()->next(12)); -reg_def XMM16n( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()->next(13)); -reg_def XMM16o( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()->next(14)); -reg_def XMM16p( SOC, SOE, Op_RegF, 16, xmm16->as_VMReg()->next(15)); - -reg_def XMM17 ( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()); -reg_def XMM17b( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(1)); -reg_def XMM17c( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(2)); -reg_def XMM17d( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(3)); -reg_def XMM17e( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(4)); -reg_def XMM17f( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(5)); -reg_def XMM17g( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(6)); -reg_def XMM17h( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(7)); -reg_def XMM17i( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(8)); -reg_def XMM17j( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(9)); -reg_def XMM17k( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(10)); -reg_def XMM17l( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(11)); -reg_def XMM17m( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(12)); -reg_def XMM17n( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(13)); -reg_def XMM17o( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(14)); -reg_def XMM17p( SOC, SOE, Op_RegF, 17, xmm17->as_VMReg()->next(15)); - -reg_def XMM18 ( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()); -reg_def XMM18b( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(1)); -reg_def XMM18c( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(2)); -reg_def XMM18d( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(3)); -reg_def XMM18e( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(4)); -reg_def XMM18f( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(5)); -reg_def XMM18g( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(6)); -reg_def XMM18h( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(7)); -reg_def XMM18i( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(8)); -reg_def XMM18j( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(9)); -reg_def XMM18k( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(10)); -reg_def XMM18l( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(11)); -reg_def XMM18m( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(12)); -reg_def XMM18n( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(13)); -reg_def XMM18o( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(14)); -reg_def XMM18p( SOC, SOE, Op_RegF, 18, xmm18->as_VMReg()->next(15)); - -reg_def XMM19 ( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()); -reg_def XMM19b( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(1)); -reg_def XMM19c( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(2)); -reg_def XMM19d( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(3)); -reg_def XMM19e( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(4)); -reg_def XMM19f( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(5)); -reg_def XMM19g( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(6)); -reg_def XMM19h( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(7)); -reg_def XMM19i( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(8)); -reg_def XMM19j( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(9)); -reg_def XMM19k( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(10)); -reg_def XMM19l( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(11)); -reg_def XMM19m( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(12)); -reg_def XMM19n( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(13)); -reg_def XMM19o( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(14)); -reg_def XMM19p( SOC, SOE, Op_RegF, 19, xmm19->as_VMReg()->next(15)); - -reg_def XMM20 ( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()); -reg_def XMM20b( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(1)); -reg_def XMM20c( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(2)); -reg_def XMM20d( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(3)); -reg_def XMM20e( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(4)); -reg_def XMM20f( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(5)); -reg_def XMM20g( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(6)); -reg_def XMM20h( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(7)); -reg_def XMM20i( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(8)); -reg_def XMM20j( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(9)); -reg_def XMM20k( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(10)); -reg_def XMM20l( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(11)); -reg_def XMM20m( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(12)); -reg_def XMM20n( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(13)); -reg_def XMM20o( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(14)); -reg_def XMM20p( SOC, SOE, Op_RegF, 20, xmm20->as_VMReg()->next(15)); - -reg_def XMM21 ( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()); -reg_def XMM21b( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(1)); -reg_def XMM21c( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(2)); -reg_def XMM21d( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(3)); -reg_def XMM21e( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(4)); -reg_def XMM21f( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(5)); -reg_def XMM21g( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(6)); -reg_def XMM21h( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(7)); -reg_def XMM21i( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(8)); -reg_def XMM21j( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(9)); -reg_def XMM21k( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(10)); -reg_def XMM21l( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(11)); -reg_def XMM21m( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(12)); -reg_def XMM21n( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(13)); -reg_def XMM21o( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(14)); -reg_def XMM21p( SOC, SOE, Op_RegF, 21, xmm21->as_VMReg()->next(15)); - -reg_def XMM22 ( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()); -reg_def XMM22b( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(1)); -reg_def XMM22c( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(2)); -reg_def XMM22d( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(3)); -reg_def XMM22e( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(4)); -reg_def XMM22f( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(5)); -reg_def XMM22g( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(6)); -reg_def XMM22h( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(7)); -reg_def XMM22i( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(8)); -reg_def XMM22j( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(9)); -reg_def XMM22k( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(10)); -reg_def XMM22l( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(11)); -reg_def XMM22m( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(12)); -reg_def XMM22n( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(13)); -reg_def XMM22o( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(14)); -reg_def XMM22p( SOC, SOE, Op_RegF, 22, xmm22->as_VMReg()->next(15)); - -reg_def XMM23 ( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()); -reg_def XMM23b( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(1)); -reg_def XMM23c( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(2)); -reg_def XMM23d( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(3)); -reg_def XMM23e( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(4)); -reg_def XMM23f( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(5)); -reg_def XMM23g( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(6)); -reg_def XMM23h( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(7)); -reg_def XMM23i( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(8)); -reg_def XMM23j( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(9)); -reg_def XMM23k( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(10)); -reg_def XMM23l( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(11)); -reg_def XMM23m( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(12)); -reg_def XMM23n( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(13)); -reg_def XMM23o( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(14)); -reg_def XMM23p( SOC, SOE, Op_RegF, 23, xmm23->as_VMReg()->next(15)); - -reg_def XMM24 ( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()); -reg_def XMM24b( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(1)); -reg_def XMM24c( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(2)); -reg_def XMM24d( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(3)); -reg_def XMM24e( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(4)); -reg_def XMM24f( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(5)); -reg_def XMM24g( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(6)); -reg_def XMM24h( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(7)); -reg_def XMM24i( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(8)); -reg_def XMM24j( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(9)); -reg_def XMM24k( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(10)); -reg_def XMM24l( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(11)); -reg_def XMM24m( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(12)); -reg_def XMM24n( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(13)); -reg_def XMM24o( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(14)); -reg_def XMM24p( SOC, SOE, Op_RegF, 24, xmm24->as_VMReg()->next(15)); - -reg_def XMM25 ( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()); -reg_def XMM25b( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(1)); -reg_def XMM25c( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(2)); -reg_def XMM25d( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(3)); -reg_def XMM25e( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(4)); -reg_def XMM25f( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(5)); -reg_def XMM25g( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(6)); -reg_def XMM25h( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(7)); -reg_def XMM25i( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(8)); -reg_def XMM25j( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(9)); -reg_def XMM25k( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(10)); -reg_def XMM25l( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(11)); -reg_def XMM25m( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(12)); -reg_def XMM25n( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(13)); -reg_def XMM25o( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(14)); -reg_def XMM25p( SOC, SOE, Op_RegF, 25, xmm25->as_VMReg()->next(15)); - -reg_def XMM26 ( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()); -reg_def XMM26b( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(1)); -reg_def XMM26c( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(2)); -reg_def XMM26d( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(3)); -reg_def XMM26e( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(4)); -reg_def XMM26f( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(5)); -reg_def XMM26g( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(6)); -reg_def XMM26h( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(7)); -reg_def XMM26i( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(8)); -reg_def XMM26j( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(9)); -reg_def XMM26k( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(10)); -reg_def XMM26l( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(11)); -reg_def XMM26m( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(12)); -reg_def XMM26n( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(13)); -reg_def XMM26o( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(14)); -reg_def XMM26p( SOC, SOE, Op_RegF, 26, xmm26->as_VMReg()->next(15)); - -reg_def XMM27g( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(1)); -reg_def XMM27c( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(2)); -reg_def XMM27d( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(3)); -reg_def XMM27e( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(4)); -reg_def XMM27f( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(5)); -reg_def XMM27g( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(6)); -reg_def XMM27h( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(7)); -reg_def XMM27i( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(8)); -reg_def XMM27j( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(9)); -reg_def XMM27k( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(10)); -reg_def XMM27l( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(11)); -reg_def XMM27m( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(12)); -reg_def XMM27n( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(13)); -reg_def XMM27o( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(14)); -reg_def XMM27p( SOC, SOE, Op_RegF, 27, xmm27->as_VMReg()->next(15)); - -reg_def XMM28 ( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()); -reg_def XMM28b( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(1)); -reg_def XMM28c( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(2)); -reg_def XMM28d( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(3)); -reg_def XMM28e( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(4)); -reg_def XMM28f( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(5)); -reg_def XMM28g( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(6)); -reg_def XMM28h( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(7)); -reg_def XMM28i( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(8)); -reg_def XMM28j( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(9)); -reg_def XMM28k( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(10)); -reg_def XMM28l( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(11)); -reg_def XMM28m( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(12)); -reg_def XMM28n( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(13)); -reg_def XMM28o( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(14)); -reg_def XMM28p( SOC, SOE, Op_RegF, 28, xmm28->as_VMReg()->next(15)); - -reg_def XMM29 ( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()); -reg_def XMM29b( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(1)); -reg_def XMM29c( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(2)); -reg_def XMM29d( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(3)); -reg_def XMM29e( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(4)); -reg_def XMM29f( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(5)); -reg_def XMM29g( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(6)); -reg_def XMM29h( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(7)); -reg_def XMM29i( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(8)); -reg_def XMM29j( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(9)); -reg_def XMM29k( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(10)); -reg_def XMM29l( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(11)); -reg_def XMM29m( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(12)); -reg_def XMM29n( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(13)); -reg_def XMM29o( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(14)); -reg_def XMM29p( SOC, SOE, Op_RegF, 29, xmm29->as_VMReg()->next(15)); - -reg_def XMM30 ( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()); -reg_def XMM30b( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(1)); -reg_def XMM30c( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(2)); -reg_def XMM30d( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(3)); -reg_def XMM30e( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(4)); -reg_def XMM30f( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(5)); -reg_def XMM30g( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(6)); -reg_def XMM30h( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(7)); -reg_def XMM30i( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(8)); -reg_def XMM30j( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(9)); -reg_def XMM30k( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(10)); -reg_def XMM30l( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(11)); -reg_def XMM30m( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(12)); -reg_def XMM30n( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(13)); -reg_def XMM30o( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(14)); -reg_def XMM30p( SOC, SOE, Op_RegF, 30, xmm30->as_VMReg()->next(15)); - -reg_def XMM31 ( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()); -reg_def XMM31b( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()->next(1)); -reg_def XMM31c( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()->next(2)); -reg_def XMM31d( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()->next(3)); -reg_def XMM31e( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()->next(4)); -reg_def XMM31f( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()->next(5)); -reg_def XMM31g( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()->next(6)); -reg_def XMM31h( SOC, SOE, Op_RegF, 31, xmm31>-as_VMReg()->next(7)); -reg_def XMM31i( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()->next(8)); -reg_def XMM31j( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()->next(9)); -reg_def XMM31k( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()->next(10)); -reg_def XMM31l( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()->next(11)); -reg_def XMM31m( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()->next(12)); -reg_def XMM31n( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()->next(13)); -reg_def XMM31o( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()->next(14)); -reg_def XMM31p( SOC, SOE, Op_RegF, 31, xmm31->as_VMReg()->next(15)); - -#else // _WIN64 - reg_def XMM6 ( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()); reg_def XMM6b( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next(1)); reg_def XMM6c( SOC, SOC, Op_RegF, 6, xmm6->as_VMReg()->next(2)); @@ -1067,8 +622,6 @@ reg_def XMM31p( SOC, SOC, Op_RegF, 31, xmm31->as_VMReg()->next(15)); #endif // _LP64 -#endif // _WIN64 - #ifdef _LP64 reg_def RFLAGS(SOC, SOC, 0, 16, VMRegImpl::Bad()); #else @@ -3113,6 +2666,30 @@ instruct onspinwait() %{ ins_pipe(pipe_slow); %} +// a * b + c +instruct fmaD_reg(regD a, regD b, regD c) %{ + predicate(UseFMA); + match(Set c (FmaD c (Binary a b))); + format %{ "fmasd $a,$b,$c\t# $c = $a * $b + $c" %} + ins_cost(150); + ins_encode %{ + __ fmad($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct fmaF_reg(regF a, regF b, regF c) %{ + predicate(UseFMA); + match(Set c (FmaF c (Binary a b))); + format %{ "fmass $a,$b,$c\t# $c = $a * $b + $c" %} + ins_cost(150); + ins_encode %{ + __ fmaf($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister); + %} + ins_pipe( pipe_slow ); +%} + // ====================VECTOR INSTRUCTIONS===================================== // Load vectors (4 bytes long) diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 4f7d3aacfd9..cbfe7668335 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -104,14 +104,14 @@ reg_def FPR7H( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next()); // // Empty fill registers, which are never used, but supply alignment to xmm regs // -reg_def FILL0( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(2)); -reg_def FILL1( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(3)); -reg_def FILL2( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(4)); -reg_def FILL3( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(5)); -reg_def FILL4( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(6)); -reg_def FILL5( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(7)); -reg_def FILL6( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(8)); -reg_def FILL7( SOC, SOC, Op_RegF, 7, as_FloatRegister(6)->as_VMReg()->next(9)); +reg_def FILL0( SOC, SOC, Op_RegF, 8, VMRegImpl::Bad()); +reg_def FILL1( SOC, SOC, Op_RegF, 9, VMRegImpl::Bad()); +reg_def FILL2( SOC, SOC, Op_RegF, 10, VMRegImpl::Bad()); +reg_def FILL3( SOC, SOC, Op_RegF, 11, VMRegImpl::Bad()); +reg_def FILL4( SOC, SOC, Op_RegF, 12, VMRegImpl::Bad()); +reg_def FILL5( SOC, SOC, Op_RegF, 13, VMRegImpl::Bad()); +reg_def FILL6( SOC, SOC, Op_RegF, 14, VMRegImpl::Bad()); +reg_def FILL7( SOC, SOC, Op_RegF, 15, VMRegImpl::Bad()); // Specify priority of register selection within phases of register // allocation. Highest priority is first. A useful heuristic is to diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java index 2e68bb8b8c9..fa67e972c06 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java @@ -205,7 +205,8 @@ public class AMD64 extends Architecture { AVX512CD, AVX512BW, AVX512VL, - SHA + SHA, + FMA } private final EnumSet features; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java index fa749bf2735..6dd1b8bd47f 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java @@ -124,6 +124,9 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto if ((config.vmVersionFeatures & config.amd64SHA) != 0) { features.add(AMD64.CPUFeature.SHA); } + if ((config.vmVersionFeatures & config.amd64FMA) != 0) { + features.add(AMD64.CPUFeature.FMA); + } return features; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java index 4506916fbdd..2881990384f 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java @@ -78,4 +78,5 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess { final long amd64AVX512BW = getConstant("VM_Version::CPU_AVX512BW", Long.class); final long amd64AVX512VL = getConstant("VM_Version::CPU_AVX512VL", Long.class); final long amd64SHA = getConstant("VM_Version::CPU_SHA", Long.class); + final long amd64FMA = getConstant("VM_Version::CPU_FMA", Long.class); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java index 00d998d69d6..1be9c651e74 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java @@ -26,8 +26,7 @@ package jdk.vm.ci.hotspot; import static jdk.vm.ci.common.InitTimer.timer; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; +import java.lang.reflect.Executable; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.InstalledCode; @@ -385,10 +384,9 @@ final class CompilerToVM { native boolean hasFinalizableSubclass(HotSpotResolvedObjectTypeImpl type); /** - * Gets the method corresponding to {@code holder} and slot number {@code slot} (i.e. - * {@link Method#slot} or {@link Constructor#slot}). + * Gets the method corresponding to {@code executable}. */ - native HotSpotResolvedJavaMethodImpl getResolvedJavaMethodAtSlot(Class holder, int slot); + native HotSpotResolvedJavaMethodImpl asResolvedJavaMethod(Executable executable); /** * Gets the maximum absolute offset of a PC relative call to {@code address} from any position @@ -616,4 +614,9 @@ final class CompilerToVM { */ native int interpreterFrameSize(BytecodeFrame frame); + /** + * Invokes non-public method {@code java.lang.invoke.LambdaForm.compileToBytecode()} on + * {@code lambdaForm} (which must be a {@code java.lang.invoke.LambdaForm} instance). + */ + native void compileToBytecode(Object lambdaForm); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java index 803f55a21f0..f5489fb18c5 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java @@ -22,7 +22,7 @@ */ package jdk.vm.ci.hotspot; -import java.lang.reflect.Field; +import java.util.Map; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.BytecodeFrame; @@ -56,16 +56,11 @@ public class HotSpotCodeCacheProvider implements CodeCacheProvider { @Override public String getMarkName(Mark mark) { int markId = (int) mark.id; - Field[] fields = runtime.getConfig().getClass().getDeclaredFields(); - for (Field f : fields) { - if (f.getName().startsWith("MARKID_")) { - f.setAccessible(true); - try { - if (f.getInt(runtime.getConfig()) == markId) { - return f.getName(); - } - } catch (Exception e) { - } + HotSpotVMConfigStore store = runtime.getConfigStore(); + for (Map.Entry e : store.getConstants().entrySet()) { + String name = e.getKey(); + if (name.startsWith("MARKID_") && e.getValue() == markId) { + return name; } } return CodeCacheProvider.super.getMarkName(mark); @@ -76,17 +71,13 @@ public class HotSpotCodeCacheProvider implements CodeCacheProvider { */ @Override public String getTargetName(Call call) { - Field[] fields = runtime.getConfig().getClass().getDeclaredFields(); - for (Field f : fields) { - if (f.getName().endsWith("Stub")) { - f.setAccessible(true); - Object address; - try { - address = f.get(runtime.getConfig()); - if (address.equals(call.target)) { - return f.getName() + ":0x" + Long.toHexString((Long) address); - } - } catch (IllegalArgumentException | IllegalAccessException e) { + if (call.target instanceof HotSpotForeignCallTarget) { + long address = ((HotSpotForeignCallTarget) call.target).address; + HotSpotVMConfigStore store = runtime.getConfigStore(); + for (Map.Entry e : store.getFields().entrySet()) { + VMField field = e.getValue(); + if (field.isStatic() && field.value != null && field.value == address) { + return e.getValue() + ":0x" + Long.toHexString(address); } } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java index 464237ada43..6a3a38b7ca2 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java @@ -28,11 +28,10 @@ import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; import java.lang.reflect.Array; -import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Field; -import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.Objects; import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.code.TargetDescription; @@ -78,35 +77,8 @@ public class HotSpotMetaAccessProvider implements MetaAccessProvider { return new HotSpotSignature(runtime, signature); } - /** - * {@link Field} object of {@link Method#slot}. - */ - private Field reflectionMethodSlot = getReflectionSlotField(Method.class); - - /** - * {@link Field} object of {@link Constructor#slot}. - */ - private Field reflectionConstructorSlot = getReflectionSlotField(Constructor.class); - - private static Field getReflectionSlotField(Class reflectionClass) { - try { - Field field = reflectionClass.getDeclaredField("slot"); - field.setAccessible(true); - return field; - } catch (NoSuchFieldException | SecurityException e) { - throw new JVMCIError(e); - } - } - public ResolvedJavaMethod lookupJavaMethod(Executable reflectionMethod) { - try { - Class holder = reflectionMethod.getDeclaringClass(); - Field slotField = reflectionMethod instanceof Constructor ? reflectionConstructorSlot : reflectionMethodSlot; - final int slot = slotField.getInt(reflectionMethod); - return runtime.getCompilerToVM().getResolvedJavaMethodAtSlot(holder, slot); - } catch (IllegalArgumentException | IllegalAccessException e) { - throw new JVMCIError(e); - } + return runtime.getCompilerToVM().asResolvedJavaMethod(Objects.requireNonNull(reflectionMethod)); } public ResolvedJavaField lookupJavaField(Field reflectionField) { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java index f6aa30241e2..c6dd6f2410b 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java @@ -24,16 +24,17 @@ package jdk.vm.ci.hotspot; import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; -import static jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl.fromObjectClass; + +import java.lang.invoke.MethodHandle; +import java.util.Objects; + import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MethodHandleAccessProvider; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.Signature; public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProvider { @@ -48,88 +49,46 @@ public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProv * possible after the {@link HotSpotJVMCIRuntime} is fully initialized. */ static class LazyInitialization { + static final ResolvedJavaType lambdaFormType; static final ResolvedJavaField methodHandleFormField; static final ResolvedJavaField lambdaFormVmentryField; - static final ResolvedJavaMethod lambdaFormCompileToBytecodeMethod; static final HotSpotResolvedJavaField memberNameVmtargetField; - static final ResolvedJavaType CLASS = fromObjectClass(LazyInitialization.class); - /** * Search for an instance field with the given name in a class. * - * @param className name of the class to search in + * @param declaringType the type declaring the field * @param fieldName name of the field to be searched * @param fieldType resolved Java type of the field * @return resolved Java field - * @throws ClassNotFoundException * @throws NoSuchFieldError */ - private static ResolvedJavaField findFieldInClass(String className, String fieldName, ResolvedJavaType fieldType) - throws ClassNotFoundException { - Class clazz = Class.forName(className); - ResolvedJavaType type = runtime().fromClass(clazz); - ResolvedJavaField[] fields = type.getInstanceFields(false); + private static ResolvedJavaField findFieldInClass(ResolvedJavaType declaringType, String fieldName, ResolvedJavaType fieldType) { + ResolvedJavaField[] fields = declaringType.getInstanceFields(false); for (ResolvedJavaField field : fields) { if (field.getName().equals(fieldName) && field.getType().equals(fieldType)) { return field; } } - throw new NoSuchFieldError(fieldType.getName() + " " + className + "." + fieldName); + throw new NoSuchFieldError(fieldType.getName() + " " + declaringType + "." + fieldName); } - private static ResolvedJavaMethod findMethodInClass(String className, String methodName, - ResolvedJavaType resultType, ResolvedJavaType[] parameterTypes) throws ClassNotFoundException { - Class clazz = Class.forName(className); - HotSpotResolvedObjectTypeImpl type = fromObjectClass(clazz); - ResolvedJavaMethod result = null; - for (ResolvedJavaMethod method : type.getDeclaredMethods()) { - if (method.getName().equals(methodName) && signatureMatches(method, resultType, parameterTypes)) { - result = method; - } - } - if (result == null) { - StringBuilder sig = new StringBuilder("("); - for (ResolvedJavaType t : parameterTypes) { - sig.append(t.getName()).append(","); - } - if (sig.length() > 1) { - sig.replace(sig.length() - 1, sig.length(), ")"); - } else { - sig.append(')'); - } - throw new NoSuchMethodError(resultType.getName() + " " + className + "." + methodName + sig.toString()); - } - return result; + private static ResolvedJavaType resolveType(Class c) { + return runtime().fromClass(c); } - private static boolean signatureMatches(ResolvedJavaMethod m, ResolvedJavaType resultType, - ResolvedJavaType[] parameterTypes) { - Signature s = m.getSignature(); - if (!s.getReturnType(CLASS).equals(resultType)) { - return false; - } - if (s.getParameterCount(false) != parameterTypes.length) { - return false; - } - for (int i = 0; i < s.getParameterCount(false); ++i) { - if (!s.getParameterType(i, CLASS).equals(parameterTypes[i])) { - return false; - } - } - return true; + private static ResolvedJavaType resolveType(String className) throws ClassNotFoundException { + return resolveType(Class.forName(className)); } static { try { - methodHandleFormField = findFieldInClass("java.lang.invoke.MethodHandle", "form", - fromObjectClass(Class.forName("java.lang.invoke.LambdaForm"))); - lambdaFormVmentryField = findFieldInClass("java.lang.invoke.LambdaForm", "vmentry", - fromObjectClass(Class.forName("java.lang.invoke.MemberName"))); - lambdaFormCompileToBytecodeMethod = findMethodInClass("java.lang.invoke.LambdaForm", "compileToBytecode", - new HotSpotResolvedPrimitiveType(JavaKind.Void), new ResolvedJavaType[]{}); - memberNameVmtargetField = (HotSpotResolvedJavaField) findFieldInClass("java.lang.invoke.MemberName", "vmtarget", - new HotSpotResolvedPrimitiveType(JavaKind.Long)); + ResolvedJavaType methodHandleType = resolveType(MethodHandle.class); + ResolvedJavaType memberNameType = resolveType("java.lang.invoke.MemberName"); + lambdaFormType = resolveType("java.lang.invoke.LambdaForm"); + methodHandleFormField = findFieldInClass(methodHandleType, "form", lambdaFormType); + lambdaFormVmentryField = findFieldInClass(lambdaFormType, "vmentry", memberNameType); + memberNameVmtargetField = (HotSpotResolvedJavaField) findFieldInClass(memberNameType, "vmtarget", resolveType(long.class)); } catch (Throwable ex) { throw new JVMCIError(ex); } @@ -173,12 +132,13 @@ public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProv return null; } - if (forceBytecodeGeneration) { - /* Invoke non-public method: MemberName LambdaForm.compileToBytecode() */ - LazyInitialization.lambdaFormCompileToBytecodeMethod.invoke(lambdaForm, new JavaConstant[0]); - } - /* Load non-public field: MemberName LambdaForm.vmentry */ JavaConstant memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm); + if (memberName.isNull() && forceBytecodeGeneration) { + Object lf = ((HotSpotObjectConstant) lambdaForm).asObject(LazyInitialization.lambdaFormType); + compilerToVM().compileToBytecode(Objects.requireNonNull(lf)); + memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm); + assert memberName.isNonNull(); + } return getTargetMethod(memberName); } @@ -200,4 +160,3 @@ public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProv return compilerToVM().getResolvedJavaMethod(object, LazyInitialization.memberNameVmtargetField.offset()); } } - diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotModifiers.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotModifiers.java new file mode 100644 index 00000000000..ba1ea96eb1c --- /dev/null +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotModifiers.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.vm.ci.hotspot; + +import static java.lang.reflect.Modifier.ABSTRACT; +import static java.lang.reflect.Modifier.FINAL; +import static java.lang.reflect.Modifier.INTERFACE; +import static java.lang.reflect.Modifier.NATIVE; +import static java.lang.reflect.Modifier.PRIVATE; +import static java.lang.reflect.Modifier.PROTECTED; +import static java.lang.reflect.Modifier.PUBLIC; +import static java.lang.reflect.Modifier.STATIC; +import static java.lang.reflect.Modifier.STRICT; +import static java.lang.reflect.Modifier.SYNCHRONIZED; +import static java.lang.reflect.Modifier.TRANSIENT; +import static java.lang.reflect.Modifier.VOLATILE; +import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; + +import java.lang.reflect.Modifier; + +/** + * The non-public modifiers in {@link Modifier} that need to be retrieved from + * {@link HotSpotVMConfig}. + */ +public class HotSpotModifiers { + + // @formatter:off + public static final int ANNOTATION = config().jvmAccAnnotation; + public static final int ENUM = config().jvmAccEnum; + public static final int VARARGS = config().jvmAccVarargs; + public static final int BRIDGE = config().jvmAccBridge; + public static final int SYNTHETIC = config().jvmAccSynthetic; + // @formatter:on + + public static int jvmClassModifiers() { + return PUBLIC | FINAL | INTERFACE | ABSTRACT | ANNOTATION | ENUM | SYNTHETIC; + } + + public static int jvmMethodModifiers() { + return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | SYNCHRONIZED | BRIDGE | VARARGS | NATIVE | ABSTRACT | STRICT | SYNTHETIC; + } + + public static int jvmFieldModifiers() { + return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | VOLATILE | TRANSIENT | ENUM | SYNTHETIC; + } +} diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index 3cd69d9a9c0..24287261984 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java @@ -22,6 +22,7 @@ */ package jdk.vm.ci.hotspot; +import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmFieldModifiers; import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; import java.lang.annotation.Annotation; @@ -29,7 +30,6 @@ import java.lang.reflect.Field; import jdk.internal.vm.annotation.Stable; import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.ModifiersProvider; import jdk.vm.ci.meta.ResolvedJavaType; /** @@ -81,7 +81,7 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField { @Override public int getModifiers() { - return modifiers & ModifiersProvider.jvmFieldModifiers(); + return modifiers & jvmFieldModifiers(); } @Override diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index dd4658d1d3d..6ebdc4b33c1 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -24,13 +24,15 @@ package jdk.vm.ci.hotspot; import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static jdk.vm.ci.hotspot.HotSpotModifiers.BRIDGE; +import static jdk.vm.ci.hotspot.HotSpotModifiers.SYNTHETIC; +import static jdk.vm.ci.hotspot.HotSpotModifiers.VARARGS; +import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmMethodModifiers; import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; import java.lang.annotation.Annotation; import java.lang.reflect.Executable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.HashMap; @@ -42,13 +44,11 @@ import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.DefaultProfilingInfo; import jdk.vm.ci.meta.ExceptionHandler; -import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaMethod; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.LineNumberTable; import jdk.vm.ci.meta.Local; import jdk.vm.ci.meta.LocalVariableTable; -import jdk.vm.ci.meta.ModifiersProvider; import jdk.vm.ci.meta.ProfilingInfo; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; @@ -210,7 +210,7 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp @Override public int getModifiers() { - return getAllModifiers() & ModifiersProvider.jvmMethodModifiers(); + return getAllModifiers() & jvmMethodModifiers(); } @Override @@ -490,6 +490,19 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp return javaMethod == null ? null : javaMethod.getAnnotation(annotationClass); } + public boolean isBridge() { + return (BRIDGE & getModifiers()) != 0; + } + + @Override + public boolean isSynthetic() { + return (SYNTHETIC & getModifiers()) != 0; + } + + public boolean isVarArgs() { + return (VARARGS & getModifiers()) != 0; + } + public boolean isDefault() { if (isConstructor()) { return false; @@ -697,27 +710,6 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp return (getFlags() & config().methodFlagsIntrinsicCandidate) != 0; } - @Override - public JavaConstant invoke(JavaConstant receiver, JavaConstant[] arguments) { - assert !isConstructor(); - Method javaMethod = (Method) toJava(); - javaMethod.setAccessible(true); - - Object[] objArguments = new Object[arguments.length]; - for (int i = 0; i < arguments.length; i++) { - objArguments[i] = HotSpotObjectConstantImpl.asBoxedValue(arguments[i]); - } - Object objReceiver = receiver != null && !receiver.isNull() ? ((HotSpotObjectConstantImpl) receiver).object() : null; - - try { - Object objResult = javaMethod.invoke(objReceiver, objArguments); - return javaMethod.getReturnType() == void.class ? null : HotSpotObjectConstantImpl.forBoxedValue(getSignature().getReturnKind(), objResult); - - } catch (IllegalAccessException | InvocationTargetException ex) { - throw new IllegalArgumentException(ex); - } - } - /** * Allocates a compile id for this method by asking the VM for one. * diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 875b08b1bf8..a7af6a61935 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -26,6 +26,7 @@ import static java.util.Objects.requireNonNull; import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; import static jdk.vm.ci.hotspot.HotSpotConstantPool.isSignaturePolymorphicHolder; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmClassModifiers; import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; @@ -49,7 +50,6 @@ import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.ModifiersProvider; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; @@ -152,7 +152,7 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem if (isArray()) { return (getElementalType().getModifiers() & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED)) | Modifier.FINAL | Modifier.ABSTRACT; } else { - return getAccessFlags() & ModifiersProvider.jvmClassModifiers(); + return getAccessFlags() & jvmClassModifiers(); } } @@ -507,7 +507,7 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem synchronized HotSpotResolvedJavaField createField(String fieldName, JavaType type, long offset, int rawFlags) { HotSpotResolvedJavaField result = null; - final int flags = rawFlags & ModifiersProvider.jvmFieldModifiers(); + final int flags = rawFlags & HotSpotModifiers.jvmFieldModifiers(); final long id = offset + ((long) flags << 32); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 64ec7c0b886..a731b8aff4d 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -117,8 +117,12 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess { final int jvmAccFieldHasGenericSignature = getConstant("JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE", Integer.class); final int jvmAccIsCloneableFast = getConstant("JVM_ACC_IS_CLONEABLE_FAST", Integer.class); - // Modifier.SYNTHETIC is not public so we get it via vmStructs. + // These modifiers are not public in Modifier so we get them via vmStructs. final int jvmAccSynthetic = getConstant("JVM_ACC_SYNTHETIC", Integer.class); + final int jvmAccAnnotation = getConstant("JVM_ACC_ANNOTATION", Integer.class); + final int jvmAccBridge = getConstant("JVM_ACC_BRIDGE", Integer.class); + final int jvmAccVarargs = getConstant("JVM_ACC_VARARGS", Integer.class); + final int jvmAccEnum = getConstant("JVM_ACC_ENUM", Integer.class); // This is only valid on AMD64. final int runtimeCallStackSize = getConstant("frame::arg_reg_save_area_bytes", Integer.class, osArch.equals("amd64") ? null : 0); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/UnsafeAccess.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/UnsafeAccess.java index c75c449f9dd..61b0f949655 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/UnsafeAccess.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/UnsafeAccess.java @@ -22,8 +22,6 @@ */ package jdk.vm.ci.hotspot; -import java.lang.reflect.Field; - import jdk.internal.misc.Unsafe; /** @@ -31,21 +29,5 @@ import jdk.internal.misc.Unsafe; */ class UnsafeAccess { - static final Unsafe UNSAFE = initUnsafe(); - - private static Unsafe initUnsafe() { - try { - // Fast path when we are trusted. - return Unsafe.getUnsafe(); - } catch (SecurityException se) { - // Slow path when we are not trusted. - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - return (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe", e); - } - } - } + static final Unsafe UNSAFE = Unsafe.getUnsafe(); } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java index fc5d260960f..c1d725d20b5 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/MetaUtil.java @@ -22,9 +22,6 @@ */ package jdk.vm.ci.meta; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; - /** * Miscellaneous collection of utility methods used by {@code jdk.vm.ci.meta} and its clients. */ @@ -226,17 +223,4 @@ public class MetaUtil { } return obj.getClass().getName() + "@" + System.identityHashCode(obj); } - - /** - * Used to lookup constants from {@link Modifier} that are not public (VARARGS, SYNTHETIC etc.). - */ - static int getNonPublicModifierStaticField(String name) { - try { - Field field = Modifier.class.getDeclaredField(name); - field.setAccessible(true); - return field.getInt(null); - } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { - throw new InternalError(e); - } - } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ModifiersProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ModifiersProvider.java index 2f28c7e31f3..c6cf9f0cec2 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ModifiersProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ModifiersProvider.java @@ -22,18 +22,9 @@ */ package jdk.vm.ci.meta; -import static java.lang.reflect.Modifier.ABSTRACT; -import static java.lang.reflect.Modifier.FINAL; -import static java.lang.reflect.Modifier.INTERFACE; -import static java.lang.reflect.Modifier.NATIVE; import static java.lang.reflect.Modifier.PRIVATE; import static java.lang.reflect.Modifier.PROTECTED; import static java.lang.reflect.Modifier.PUBLIC; -import static java.lang.reflect.Modifier.STATIC; -import static java.lang.reflect.Modifier.STRICT; -import static java.lang.reflect.Modifier.SYNCHRONIZED; -import static java.lang.reflect.Modifier.TRANSIENT; -import static java.lang.reflect.Modifier.VOLATILE; import java.lang.reflect.Modifier; @@ -42,17 +33,9 @@ import java.lang.reflect.Modifier; * language {@linkplain #getModifiers() modifiers}. */ public interface ModifiersProvider { - int BRIDGE = MetaUtil.getNonPublicModifierStaticField("BRIDGE"); - int VARARGS = MetaUtil.getNonPublicModifierStaticField("VARARGS"); - int SYNTHETIC = MetaUtil.getNonPublicModifierStaticField("SYNTHETIC"); - int ANNOTATION = MetaUtil.getNonPublicModifierStaticField("ANNOTATION"); - int ENUM = MetaUtil.getNonPublicModifierStaticField("ENUM"); - int MANDATED = MetaUtil.getNonPublicModifierStaticField("MANDATED"); /** - * Returns the Java Virtual Machine modifiers for this element. Note that this can differ from - * standard Java Reflection modifiers. For example at the JVM level, classes ( - * {@link ResolvedJavaType}) can not be private or protected. + * Returns the modifiers for this element. */ int getModifiers(); @@ -161,17 +144,4 @@ public interface ModifiersProvider { default boolean isConcrete() { return !isAbstract(); } - - static int jvmClassModifiers() { - // no SUPER - return PUBLIC | FINAL | INTERFACE | ABSTRACT | ANNOTATION | ENUM | SYNTHETIC; - } - - static int jvmMethodModifiers() { - return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | SYNCHRONIZED | BRIDGE | VARARGS | NATIVE | ABSTRACT | STRICT | SYNTHETIC; - } - - static int jvmFieldModifiers() { - return PUBLIC | PRIVATE | PROTECTED | STATIC | FINAL | VOLATILE | TRANSIENT | ENUM | SYNTHETIC; - } } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java index 3b2facc26d9..5a56981e9e4 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -26,7 +26,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Array; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.lang.reflect.Type; /** @@ -72,14 +71,6 @@ public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersP */ int getMaxStackSize(); - /** - * {@inheritDoc} - *

- * Only the {@linkplain Modifier#methodModifiers() method flags} specified in the JVM - * specification will be included in the returned mask. - */ - int getModifiers(); - default boolean isFinal() { return ModifiersProvider.super.isFinalFlagSet(); } @@ -88,9 +79,7 @@ public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersP * Determines if this method is a synthetic method as defined by the Java Language * Specification. */ - default boolean isSynthetic() { - return (SYNTHETIC & getModifiers()) == SYNTHETIC; - } + boolean isSynthetic(); /** * Checks that the method is a @@ -99,9 +88,7 @@ public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersP * * @return whether the method is a varargs method */ - default boolean isVarArgs() { - return (VARARGS & getModifiers()) == VARARGS; - } + boolean isVarArgs(); /** * Checks that the method is a @@ -110,9 +97,7 @@ public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersP * * @return whether the method is a bridge method */ - default boolean isBridge() { - return (BRIDGE & getModifiers()) == BRIDGE; - } + boolean isBridge(); /** * Returns {@code true} if this method is a default method; returns {@code false} otherwise. @@ -227,18 +212,6 @@ public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersP */ LocalVariableTable getLocalVariableTable(); - /** - * Invokes the underlying method represented by this object, on the specified object with the - * specified parameters. This method is similar to a reflective method invocation by - * {@link Method#invoke}. - * - * @param receiver The receiver for the invocation, or {@code null} if it is a static method. - * @param arguments The arguments for the invocation. - * @return The value returned by the method invocation, or {@code null} if the return type is - * {@code void}. - */ - JavaConstant invoke(JavaConstant receiver, JavaConstant[] arguments); - /** * Gets the encoding of (that is, a constant representing the value of) this method. * diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java index 43cc6a62d9f..891e7943de3 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/ResolvedJavaType.java @@ -68,15 +68,6 @@ public interface ResolvedJavaType extends JavaType, ModifiersProvider, Annotated */ boolean isPrimitive(); - /** - * {@inheritDoc} - *

- * Only the flags specified in the JVM specification will be included in the returned mask. This - * method is identical to {@link Class#getModifiers()} in terms of the value return for this - * type. - */ - int getModifiers(); - /* * The setting of the final bit for types is a bit confusing since arrays are marked as final. * This method provides a semantically equivalent test that appropriate for types. diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 3b075455d92..5af74d3668f 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -2366,7 +2366,9 @@ bool os::win32::get_frame_at_stack_banging_point(JavaThread* thread, if (Interpreter::contains(pc)) { *fr = os::fetch_frame_from_context((void*)exceptionInfo->ContextRecord); if (!fr->is_first_java_frame()) { - assert(fr->safe_for_sender(thread), "Safety check"); + // get_frame_at_stack_banging_point() is only called when we + // have well defined stacks so java_sender() calls do not need + // to assert safe_for_sender() first. *fr = fr->java_sender(); } } else { @@ -2383,7 +2385,7 @@ bool os::win32::get_frame_at_stack_banging_point(JavaThread* thread, // has been pushed on the stack *fr = frame(fr->sp() + 1, fr->fp(), (address)*(fr->sp())); if (!fr->is_java_frame()) { - assert(fr->safe_for_sender(thread), "Safety check"); + // See java_sender() comment above. *fr = fr->java_sender(); } } diff --git a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp index 6e3de2d6f9e..d9d8da7395a 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp @@ -378,7 +378,9 @@ bool os::Bsd::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* u // method returns the Java sender of the current frame. *fr = os::fetch_frame_from_ucontext(thread, uc); if (!fr->is_first_java_frame()) { - assert(fr->safe_for_sender(thread), "Safety check"); + // get_frame_at_stack_banging_point() is only called when we + // have well defined stacks so java_sender() calls do not need + // to assert safe_for_sender() first. *fr = fr->java_sender(); } } else { @@ -395,7 +397,7 @@ bool os::Bsd::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* u // has been pushed on the stack *fr = frame(fr->sp() + 1, fr->fp(), (address)*(fr->sp())); if (!fr->is_java_frame()) { - assert(fr->safe_for_sender(thread), "Safety check"); + // See java_sender() comment above. *fr = fr->java_sender(); } } diff --git a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp index e7566c7d4af..0bf4b8db7fc 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp +++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp @@ -191,7 +191,9 @@ bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* // method returns the Java sender of the current frame. *fr = os::fetch_frame_from_ucontext(thread, uc); if (!fr->is_first_java_frame()) { - assert(fr->safe_for_sender(thread), "Safety check"); + // get_frame_at_stack_banging_point() is only called when we + // have well defined stacks so java_sender() calls do not need + // to assert safe_for_sender() first. *fr = fr->java_sender(); } } else { @@ -209,8 +211,8 @@ bool os::Linux::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_t* intptr_t* sp = os::Linux::ucontext_get_sp(uc); *fr = frame(sp + 1, fp, (address)*sp); if (!fr->is_java_frame()) { - assert(fr->safe_for_sender(thread), "Safety check"); assert(!fr->is_first_frame(), "Safety check"); + // See java_sender() comment above. *fr = fr->java_sender(); } } diff --git a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp index bc79053f81d..530f7033df9 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp @@ -255,7 +255,9 @@ bool os::Solaris::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_ // method returns the Java sender of the current frame. *fr = os::fetch_frame_from_ucontext(thread, uc); if (!fr->is_first_java_frame()) { - assert(fr->safe_for_sender(thread), "Safety check"); + // get_frame_at_stack_banging_point() is only called when we + // have well defined stacks so java_sender() calls do not need + // to assert safe_for_sender() first. *fr = fr->java_sender(); } } else { @@ -273,7 +275,7 @@ bool os::Solaris::get_frame_at_stack_banging_point(JavaThread* thread, ucontext_ intptr_t* sp = os::Solaris::ucontext_get_sp(uc); *fr = frame(sp + 1, fp, (address)*sp); if (!fr->is_java_frame()) { - assert(fr->safe_for_sender(thread), "Safety check"); + // See java_sender() comment above. *fr = fr->java_sender(); } } diff --git a/hotspot/src/share/vm/adlc/formssel.cpp b/hotspot/src/share/vm/adlc/formssel.cpp index 7f720b1b708..5f748379655 100644 --- a/hotspot/src/share/vm/adlc/formssel.cpp +++ b/hotspot/src/share/vm/adlc/formssel.cpp @@ -1245,6 +1245,7 @@ bool InstructForm::check_branch_variant(ArchDesc &AD, InstructForm *short_branch this != short_branch && // Don't match myself !is_short_branch() && // Don't match another short branch variant reduce_result() != NULL && + strstr(_ident, "restoreMask") == NULL && // Don't match side effects strcmp(reduce_result(), short_branch->reduce_result()) == 0 && _matrule->equivalent(AD.globalNames(), short_branch->_matrule)) { // The instructions are equivalent. @@ -4037,6 +4038,8 @@ int MatchRule::is_expensive() const { strcmp(opType,"EncodeP")==0 || strcmp(opType,"EncodePKlass")==0 || strcmp(opType,"DecodeNKlass")==0 || + strcmp(opType,"FmaD") == 0 || + strcmp(opType,"FmaF") == 0 || strcmp(opType,"RoundDouble")==0 || strcmp(opType,"RoundFloat")==0 || strcmp(opType,"ReverseBytesI")==0 || diff --git a/hotspot/src/share/vm/c1/c1_Compiler.cpp b/hotspot/src/share/vm/c1/c1_Compiler.cpp index 08f2fdddb85..b25255bd7db 100644 --- a/hotspot/src/share/vm/c1/c1_Compiler.cpp +++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp @@ -162,6 +162,8 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) { case vmIntrinsics::_dlog10: case vmIntrinsics::_dexp: case vmIntrinsics::_dpow: + case vmIntrinsics::_fmaD: + case vmIntrinsics::_fmaF: case vmIntrinsics::_getObject: case vmIntrinsics::_getBoolean: case vmIntrinsics::_getByte: diff --git a/hotspot/src/share/vm/c1/c1_LIR.cpp b/hotspot/src/share/vm/c1/c1_LIR.cpp index ced682b5c0b..8c577be0918 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.cpp +++ b/hotspot/src/share/vm/c1/c1_LIR.cpp @@ -666,7 +666,9 @@ void LIR_OpVisitState::visit(LIR_Op* op) { // LIR_Op3 case lir_idiv: - case lir_irem: { + case lir_irem: + case lir_fmad: + case lir_fmaf: { assert(op->as_Op3() != NULL, "must be"); LIR_Op3* op3= (LIR_Op3*)op; @@ -1663,6 +1665,8 @@ const char * LIR_Op::name() const { // LIR_Op3 case lir_idiv: s = "idiv"; break; case lir_irem: s = "irem"; break; + case lir_fmad: s = "fmad"; break; + case lir_fmaf: s = "fmaf"; break; // LIR_OpJavaCall case lir_static_call: s = "static"; break; case lir_optvirtual_call: s = "optvirtual"; break; diff --git a/hotspot/src/share/vm/c1/c1_LIR.hpp b/hotspot/src/share/vm/c1/c1_LIR.hpp index 7ca75ff3ebe..79d298d4cdf 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.hpp +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp @@ -956,6 +956,8 @@ enum LIR_Code { , begin_op3 , lir_idiv , lir_irem + , lir_fmad + , lir_fmaf , end_op3 , begin_opJavaCall , lir_static_call @@ -2149,6 +2151,8 @@ class LIR_List: public CompilationResourceObj { void abs (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_abs , from, tmp, to)); } void sqrt(LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_sqrt, from, tmp, to)); } + void fmad(LIR_Opr from, LIR_Opr from1, LIR_Opr from2, LIR_Opr to) { append(new LIR_Op3(lir_fmad, from, from1, from2, to)); } + void fmaf(LIR_Opr from, LIR_Opr from1, LIR_Opr from2, LIR_Opr to) { append(new LIR_Op3(lir_fmaf, from, from1, from2, to)); } void log10 (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_log10, from, LIR_OprFact::illegalOpr, to, tmp)); } void tan (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_tan , from, tmp1, to, tmp2)); } diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 3a5d4ca90c2..65c13d5912f 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -3181,6 +3181,9 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) { case vmIntrinsics::_dpow : do_MathIntrinsic(x); break; case vmIntrinsics::_arraycopy: do_ArrayCopy(x); break; + case vmIntrinsics::_fmaD: do_FmaIntrinsic(x); break; + case vmIntrinsics::_fmaF: do_FmaIntrinsic(x); break; + // java.nio.Buffer.checkIndex case vmIntrinsics::_checkIndex: do_NIOCheckIndex(x); break; @@ -3244,14 +3247,14 @@ void LIRGenerator::profile_arguments(ProfileCall* x) { Bytecodes::Code bc = x->method()->java_code_at_bci(bci); int start = 0; int stop = data->is_CallTypeData() ? ((ciCallTypeData*)data)->number_of_arguments() : ((ciVirtualCallTypeData*)data)->number_of_arguments(); - if (x->inlined() && x->callee()->is_static() && Bytecodes::has_receiver(bc)) { + if (x->callee()->is_loaded() && x->callee()->is_static() && Bytecodes::has_receiver(bc)) { // first argument is not profiled at call (method handle invoke) assert(x->method()->raw_code_at_bci(bci) == Bytecodes::_invokehandle, "invokehandle expected"); start = 1; } ciSignature* callee_signature = x->callee()->signature(); // method handle call to virtual method - bool has_receiver = x->inlined() && !x->callee()->is_static() && !Bytecodes::has_receiver(bc); + bool has_receiver = x->callee()->is_loaded() && !x->callee()->is_static() && !Bytecodes::has_receiver(bc); ciSignatureStream callee_signature_stream(callee_signature, has_receiver ? x->callee()->holder() : NULL); bool ignored_will_link; diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp index cda06580660..04dae206422 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp @@ -245,6 +245,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void do_isPrimitive(Intrinsic* x); void do_getClass(Intrinsic* x); void do_currentThread(Intrinsic* x); + void do_FmaIntrinsic(Intrinsic* x); void do_MathIntrinsic(Intrinsic* x); void do_LibmIntrinsic(Intrinsic* x); void do_ArrayCopy(Intrinsic* x); diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index 6e74496d80c..46847f67644 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -85,6 +85,7 @@ typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsig typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n); typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg); typedef jint (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len); +typedef void (JNICALL *FreeEntry_t)(jzfile *zip, jzentry *entry); static ZipOpen_t ZipOpen = NULL; static ZipClose_t ZipClose = NULL; @@ -95,6 +96,7 @@ static GetNextEntry_t GetNextEntry = NULL; static canonicalize_fn_t CanonicalizeEntry = NULL; static ZipInflateFully_t ZipInflateFully = NULL; static Crc32_t Crc32 = NULL; +static FreeEntry_t FreeEntry = NULL; // Entry points for jimage.dll for loading jimage file entries @@ -150,6 +152,7 @@ int ClassLoader::_num_entries = 0; GrowableArray* ClassLoader::_boot_modules_array = NULL; GrowableArray* ClassLoader::_platform_modules_array = NULL; SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL; +int ClassLoader::_num_patch_mod_prefixes = 0; #endif // helper routines @@ -319,6 +322,20 @@ ClassPathZipEntry::~ClassPathZipEntry() { FREE_C_HEAP_ARRAY(char, _zip_name); } +bool ClassPathZipEntry::stream_exists(const char* name) { + // enable call to C land + JavaThread* thread = JavaThread::current(); + ThreadToNativeFromVM ttn(thread); + // check whether zip archive contains name + jint name_len, filesize; + jzentry* entry = (*FindEntry)(_zip, name, &filesize, &name_len); + if (entry != NULL) { + (*FreeEntry)(_zip, entry); + return true; + } + return false; +} + u1* ClassPathZipEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) { // enable call to C land JavaThread* thread = JavaThread::current(); @@ -640,7 +657,7 @@ void ClassLoader::check_shared_classpath(const char *path) { struct stat st; if (os::stat(path, &st) == 0) { - if ((st.st_mode & S_IFREG) != S_IFREG) { // is directory + if ((st.st_mode & S_IFMT) != S_IFREG) { // is not a regular file if (!os::dir_is_empty(path)) { tty->print_cr("Error: non-empty directory '%s'", path); exit_with_path_failure("CDS allows only empty directories in archived classpaths", NULL); @@ -693,8 +710,6 @@ void ClassLoader::setup_patch_mod_entries() { GrowableArray* patch_mod_args = Arguments::get_patch_mod_prefix(); int num_of_entries = patch_mod_args->length(); - assert(!DumpSharedSpaces, "DumpSharedSpaces not supported with --patch-module"); - assert(!UseSharedSpaces, "UseSharedSpaces not supported with --patch-module"); // Set up the boot loader's _patch_mod_entries list _patch_mod_entries = new (ResourceObj::C_HEAP, mtModule) GrowableArray(num_of_entries, true); @@ -851,7 +866,7 @@ ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const str bool is_boot_append, TRAPS) { JavaThread* thread = JavaThread::current(); ClassPathEntry* new_entry = NULL; - if ((st->st_mode & S_IFREG) == S_IFREG) { + if ((st->st_mode & S_IFMT) == S_IFREG) { ResourceMark rm(thread); // Regular file, should be a zip or jimage file // Canonicalized filename @@ -914,7 +929,7 @@ ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path, bo // check for a regular file struct stat st; if (os::stat(path, &st) == 0) { - if ((st.st_mode & S_IFREG) == S_IFREG) { + if ((st.st_mode & S_IFMT) == S_IFREG) { char canonical_path[JVM_MAXPATHLEN]; if (get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { char* error_msg = NULL; @@ -1068,6 +1083,7 @@ void ClassLoader::load_zip_library() { GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry")); ZipInflateFully = CAST_TO_FN_PTR(ZipInflateFully_t, os::dll_lookup(handle, "ZIP_InflateFully")); Crc32 = CAST_TO_FN_PTR(Crc32_t, os::dll_lookup(handle, "ZIP_CRC32")); + FreeEntry = CAST_TO_FN_PTR(FreeEntry_t, os::dll_lookup(handle, "ZIP_FreeEntry")); // ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || @@ -1395,6 +1411,57 @@ ClassFileStream* ClassLoader::search_module_entries(const GrowableArraylength(); + char* class_module_name = NULL; + ResourceMark rm; + const char *pkg_name = package_from_name(file_name); + // Using the jimage to obtain the class' module name. + // The ModuleEntryTable cannot be used at this point during dump time + // because the module system hasn't been initialized yet. + if (pkg_name != NULL) { + JImageFile *jimage = _jrt_entry->jimage(); + class_module_name = (char*)(*JImagePackageToModule)(jimage, pkg_name); + } + + if (class_module_name == NULL) { + return false; + } + + // Loop through all the patch module entries looking for module + for (int i = 0; i < num_of_entries; i++) { + ModuleClassPathList* module_cpl = _patch_mod_entries->at(i); + Symbol* module_cpl_name = module_cpl->module_name(); + + if (strcmp(module_cpl_name->as_C_string(), class_module_name) == 0) { + // Class' module has been located, attempt to locate + // the class from the module's ClassPathEntry list. + ClassPathEntry* e = module_cpl->module_first_entry(); + while (e != NULL) { + if (e->is_jar_file()) { + if (e->stream_exists(file_name)) { + return true; + } else { + e = e->next(); + } + } + } + } + } + + return false; +} +#endif // INCLUDE_CDS + instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS) { assert(name != NULL, "invariant"); assert(THREAD->is_Java_thread(), "must be a JavaThread"); @@ -1420,8 +1487,8 @@ instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_onl // If DumpSharedSpaces is true boot loader visibility boundaries are set to: // - [jimage] + [_first_append_entry to _last_append_entry] (all path entries). - // No --patch-module entries or exploded module builds are included since CDS - // is not supported if --patch-module or exploded module builds are used. + // If a class is found in the --patch-module entries, the class will not be included in the + // CDS archive. Also, CDS is not supported if exploded module builds are used. // // If search_append_only is true, boot loader visibility boundaries are // set to be _first_append_entry to the end. This includes: @@ -1444,8 +1511,17 @@ instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_onl // found within its module specification, the search should continue to Load Attempt #2. // Note: The --patch-module entries are never searched if the boot loader's // visibility boundary is limited to only searching the append entries. - if (_patch_mod_entries != NULL && !search_append_only && !DumpSharedSpaces) { - stream = search_module_entries(_patch_mod_entries, class_name, file_name, CHECK_NULL); + if (_patch_mod_entries != NULL && !search_append_only) { + if (!DumpSharedSpaces) { + stream = search_module_entries(_patch_mod_entries, class_name, file_name, CHECK_NULL); + } else { +#if INCLUDE_CDS + if (is_in_patch_module(file_name)) { + tty->print_cr("Preload Warning: Skip archiving class %s found in --patch-module entry", class_name); + return NULL; + } +#endif + } } // Load Attempt #2: [jimage | exploded build] @@ -1596,8 +1672,57 @@ void ClassLoader::initialize() { } #if INCLUDE_CDS +// Capture all the --patch-module entries specified during CDS dump time. +// It also captures the non-existing path(s) and the required file(s) during inspecting +// the entries. +void ClassLoader::setup_patch_mod_path() { + assert(DumpSharedSpaces, "only used with -Xshare:dump"); + ResourceMark rm; + GrowableArray* patch_mod_args = Arguments::get_patch_mod_prefix(); + if (patch_mod_args != NULL) { + int num_of_entries = patch_mod_args->length(); + for (int i = 0; i < num_of_entries; i++) { + const char* module_name = (patch_mod_args->at(i))->module_name(); + const char* module_path = (patch_mod_args->at(i))->path_string(); + int path_len = (int)strlen(module_path); + int name_len = (int)strlen(module_name); + int buf_len = name_len + path_len + 2; // add 2 for the '=' and NULL terminator + int end = 0; + char* buf = NEW_C_HEAP_ARRAY(char, buf_len, mtInternal); + // Iterate over the module's class path entries + for (int start = 0; start < path_len; start = end) { + while (module_path[end] && module_path[end] != os::path_separator()[0]) { + end++; + } + strncpy(buf, &module_path[start], end - start); + buf[end - start] = '\0'; + struct stat st; + if (os::stat(buf, &st) != 0) { + // File not found + _shared_paths_misc_info->add_nonexist_path(buf); + } else { + if ((st.st_mode & S_IFMT) != S_IFREG) { // is not a regular file + vm_exit_during_initialization( + "--patch-module requires a regular file during dumping", buf); + } else { + _shared_paths_misc_info->add_required_file(buf); + } + } + while (module_path[end] == os::path_separator()[0]) { + end++; + } + }; + jio_snprintf(buf, buf_len, "%s=%s", module_name, module_path); + _shared_paths_misc_info->add_patch_mod_classpath((const char*)buf); + _num_patch_mod_prefixes++; + FREE_C_HEAP_ARRAY(char, buf); + } + } +} + void ClassLoader::initialize_shared_path() { if (DumpSharedSpaces) { + setup_patch_mod_path(); ClassLoaderExt::setup_search_paths(); _shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check() } diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp index 35c000a6be1..8e7811af1b1 100644 --- a/hotspot/src/share/vm/classfile/classLoader.hpp +++ b/hotspot/src/share/vm/classfile/classLoader.hpp @@ -69,6 +69,7 @@ public: // Attempt to locate file_name through this class path entry. // Returns a class file parsing stream if successfull. virtual ClassFileStream* open_stream(const char* name, TRAPS) = 0; + virtual bool stream_exists(const char* name) = 0; // Debugging NOT_PRODUCT(virtual void compile_the_world(Handle loader, TRAPS) = 0;) }; @@ -83,6 +84,7 @@ class ClassPathDirEntry: public ClassPathEntry { JImageFile* jimage() const { return NULL; } ClassPathDirEntry(const char* dir); ClassFileStream* open_stream(const char* name, TRAPS); + bool stream_exists(const char* name) { return false; } // Debugging NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);) }; @@ -126,6 +128,7 @@ class ClassPathZipEntry: public ClassPathEntry { ClassFileStream* open_stream(const char* name, TRAPS); void contents_do(void f(const char* name, void* context), void* context); bool is_multiple_versioned(TRAPS) NOT_CDS_RETURN_(false); + bool stream_exists(const char* name); // Debugging NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);) }; @@ -145,6 +148,7 @@ public: ClassPathImageEntry(JImageFile* jimage, const char* name); ~ClassPathImageEntry(); ClassFileStream* open_stream(const char* name, TRAPS); + bool stream_exists(const char* name) { return false; } // Debugging NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);) @@ -255,6 +259,7 @@ class ClassLoader: AllStatic { // Info used by CDS CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;) + CDS_ONLY(static int _num_patch_mod_prefixes;) // Initialization: // - setup the boot loader's system class path @@ -427,6 +432,9 @@ class ClassLoader: AllStatic { static void initialize_module_loader_map(JImageFile* jimage); static s2 classloader_type(Symbol* class_name, ClassPathEntry* e, int classpath_index, TRAPS); + static bool is_in_patch_module(const char* const file_name); + static void setup_patch_mod_path(); // Only when -Xshare:dump + static int num_patch_mod_prefixes() { return _num_patch_mod_prefixes; } #endif static void trace_class_path(const char* msg, const char* name = NULL); diff --git a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp index 36cf234c2d1..178444988b0 100644 --- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp +++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp @@ -86,6 +86,9 @@ void SharedPathsMiscInfo::print_path(int type, const char* path) { case REQUIRED: out->print("Expecting that file %s must exist and is not altered", path); break; + case PATCH_MOD: + out->print("Expecting --patch-module=%s", path); + break; default: ShouldNotReachHere(); } @@ -146,6 +149,9 @@ bool SharedPathsMiscInfo::check(jint type, const char* path) { // But we want it to not exist -> fail return fail("File must not exist"); } + if ((st.st_mode & S_IFMT) != S_IFREG) { + return fail("Did not get a regular file as expected."); + } time_t timestamp; long filesize; @@ -161,7 +167,26 @@ bool SharedPathsMiscInfo::check(jint type, const char* path) { } } break; - + case PATCH_MOD: + { + GrowableArray* patch_mod_args = Arguments::get_patch_mod_prefix(); + if (patch_mod_args != NULL) { + int num_of_entries = patch_mod_args->length(); + for (int i = 0; i < num_of_entries; i++) { + const char* module_name = (patch_mod_args->at(i))->module_name(); + const char* path_string = (patch_mod_args->at(i))->path_string(); + size_t n = strlen(module_name); + // path contains the module name, followed by '=', and one or more entries. + // E.g.: "java.base=foo" or "java.naming=dir1:dir2:dir3" + if ((strncmp(module_name, path, n) != 0) || + (path[n] != '=') || + (strcmp(path + n + 1, path_string) != 0)) { + return fail("--patch-module mismatch, path not found in run time: ", path); + } + } + } + } + break; default: return fail("Corrupted archive file header"); } diff --git a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp index 77de03b0a33..c680d3f7643 100644 --- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp +++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp @@ -104,10 +104,28 @@ public: add_path(path, NON_EXIST); } + // The path must exist and have required size and modification time + void add_required_file(const char* path) { + add_path(path, REQUIRED); + + struct stat st; + if (os::stat(path, &st) != 0) { + assert(0, "sanity"); +#if INCLUDE_CDS + ClassLoader::exit_with_path_failure("failed to os::stat(%s)", path); // should not happen +#endif + } + write_time(st.st_mtime); + write_long(st.st_size); + } + // The path must exist, and must contain exactly files/dirs void add_boot_classpath(const char* path) { add_path(path, BOOT); } + void add_patch_mod_classpath(const char* path) { + add_path(path, PATCH_MOD); + } int write_jint(jint num) { write(&num, sizeof(num)); return 0; @@ -129,7 +147,8 @@ public: enum { BOOT = 1, NON_EXIST = 2, - REQUIRED = 3 + REQUIRED = 3, + PATCH_MOD = 4 }; virtual const char* type_name(int type) { @@ -137,6 +156,7 @@ public: case BOOT: return "BOOT"; case NON_EXIST: return "NON_EXIST"; case REQUIRED: return "REQUIRED"; + case PATCH_MOD: return "PATCH_MOD"; default: ShouldNotReachHere(); return "?"; } } diff --git a/hotspot/src/share/vm/classfile/symbolTable.cpp b/hotspot/src/share/vm/classfile/symbolTable.cpp index 8f51f527508..5121fdbcd64 100644 --- a/hotspot/src/share/vm/classfile/symbolTable.cpp +++ b/hotspot/src/share/vm/classfile/symbolTable.cpp @@ -710,53 +710,3 @@ int SymboltableDCmd::num_arguments() { return 0; } } - -#ifndef PRODUCT -// Internal test of TempNewSymbol -void Test_TempNewSymbol() { - // Assert messages assume these symbols are unique, and the refcounts start at - // one, but code does not rely on this. - Thread* THREAD = Thread::current(); - Symbol* abc = SymbolTable::new_symbol("abc", CATCH); - int abccount = abc->refcount(); - TempNewSymbol ss = abc; - assert(ss->refcount() == abccount, "only one abc"); - assert(ss->refcount() == abc->refcount(), "should match TempNewSymbol"); - - Symbol* efg = SymbolTable::new_symbol("efg", CATCH); - Symbol* hij = SymbolTable::new_symbol("hij", CATCH); - int efgcount = efg->refcount(); - int hijcount = hij->refcount(); - - TempNewSymbol s1 = efg; - TempNewSymbol s2 = hij; - assert(s1->refcount() == efgcount, "one efg"); - assert(s2->refcount() == hijcount, "one hij"); - - // Assignment operator - s1 = s2; - assert(hij->refcount() == hijcount + 1, "should be two hij"); - assert(efg->refcount() == efgcount - 1, "should be no efg"); - - s1 = ss; // s1 is abc - assert(s1->refcount() == abccount + 1, "should be two abc (s1 and ss)"); - assert(hij->refcount() == hijcount, "should only have one hij now (s2)"); - - s1 = s1; // self assignment - assert(s1->refcount() == abccount + 1, "should still be two abc (s1 and ss)"); - - TempNewSymbol s3; - Symbol* klm = SymbolTable::new_symbol("klm", CATCH); - int klmcount = klm->refcount(); - s3 = klm; // assignment - assert(s3->refcount() == klmcount, "only one klm now"); - - Symbol* xyz = SymbolTable::new_symbol("xyz", CATCH); - int xyzcount = xyz->refcount(); - { // inner scope - TempNewSymbol s_inner = xyz; - } - assert(xyz->refcount() == (xyzcount - 1), - "Should have been decremented by dtor in inner scope"); -} -#endif // PRODUCT diff --git a/hotspot/src/share/vm/classfile/vmSymbols.cpp b/hotspot/src/share/vm/classfile/vmSymbols.cpp index 10a77f3f4f7..ad17837fb0d 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.cpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp @@ -355,6 +355,8 @@ bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) { case vmIntrinsics::_updateBytesCRC32: case vmIntrinsics::_updateByteBufferCRC32: case vmIntrinsics::_vectorizedMismatch: + case vmIntrinsics::_fmaD: + case vmIntrinsics::_fmaF: return true; default: return false; @@ -388,6 +390,8 @@ bool vmIntrinsics::can_trap(vmIntrinsics::ID id) { case vmIntrinsics::_updateBytesCRC32: case vmIntrinsics::_updateByteBufferCRC32: case vmIntrinsics::_vectorizedMismatch: + case vmIntrinsics::_fmaD: + case vmIntrinsics::_fmaF: return false; default: return true; @@ -536,6 +540,10 @@ bool vmIntrinsics::is_disabled_by_flags(vmIntrinsics::ID id) { case vmIntrinsics::_doubleToLongBits: if (!InlineMathNatives) return true; break; + case vmIntrinsics::_fmaD: + case vmIntrinsics::_fmaF: + if (!InlineMathNatives || !UseFMA) return true; + break; case vmIntrinsics::_arraycopy: if (!InlineArrayCopy) return true; break; diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index aedc036a7ed..fd3b3fe4173 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -755,8 +755,10 @@ do_class(java_lang_Math, "java/lang/Math") \ do_class(java_lang_StrictMath, "java/lang/StrictMath") \ do_signature(double2_double_signature, "(DD)D") \ + do_signature(double3_double_signature, "(DDD)D") \ + do_signature(float3_float_signature, "(FFF)F") \ do_signature(int2_int_signature, "(II)I") \ - do_signature(long2_long_signature, "(JJ)J") \ + do_signature(long2_long_signature, "(JJ)J") \ \ /* here are the math names, all together: */ \ do_name(abs_name,"abs") do_name(sin_name,"sin") do_name(cos_name,"cos") \ @@ -770,6 +772,7 @@ do_name(multiplyExact_name,"multiplyExact") \ do_name(negateExact_name,"negateExact") \ do_name(subtractExact_name,"subtractExact") \ + do_name(fma_name, "fma") \ \ do_intrinsic(_dabs, java_lang_Math, abs_name, double_double_signature, F_S) \ do_intrinsic(_dsin, java_lang_Math, sin_name, double_double_signature, F_S) \ @@ -795,6 +798,8 @@ do_intrinsic(_negateExactL, java_lang_Math, negateExact_name, long_long_signature, F_S) \ do_intrinsic(_subtractExactI, java_lang_Math, subtractExact_name, int2_int_signature, F_S) \ do_intrinsic(_subtractExactL, java_lang_Math, subtractExact_name, long2_long_signature, F_S) \ + do_intrinsic(_fmaD, java_lang_Math, fma_name, double3_double_signature, F_S) \ + do_intrinsic(_fmaF, java_lang_Math, fma_name, float3_float_signature, F_S) \ \ do_intrinsic(_floatToRawIntBits, java_lang_Float, floatToRawIntBits_name, float_int_signature, F_S) \ do_name( floatToRawIntBits_name, "floatToRawIntBits") \ diff --git a/hotspot/src/share/vm/gc/cms/cmsOopClosures.hpp b/hotspot/src/share/vm/gc/cms/cmsOopClosures.hpp index 165ab17e682..11416afebc9 100644 --- a/hotspot/src/share/vm/gc/cms/cmsOopClosures.hpp +++ b/hotspot/src/share/vm/gc/cms/cmsOopClosures.hpp @@ -258,16 +258,15 @@ class PushOrMarkClosure: public MetadataAwareOopClosure { // the closure ParMarkFromRootsClosure. class ParPushOrMarkClosure: public MetadataAwareOopClosure { private: - CMSCollector* _collector; - MemRegion _whole_span; - MemRegion _span; // local chunk - CMSBitMap* _bit_map; - OopTaskQueue* _work_queue; - CMSMarkStack* _overflow_stack; - HeapWord* const _finger; - HeapWord** const _global_finger_addr; - ParMarkFromRootsClosure* const - _parent; + CMSCollector* _collector; + MemRegion _whole_span; + MemRegion _span; // local chunk + CMSBitMap* _bit_map; + OopTaskQueue* _work_queue; + CMSMarkStack* _overflow_stack; + HeapWord* const _finger; + HeapWord* volatile* const _global_finger_addr; + ParMarkFromRootsClosure* const _parent; protected: DO_OOP_WORK_DEFN public: @@ -277,7 +276,7 @@ class ParPushOrMarkClosure: public MetadataAwareOopClosure { OopTaskQueue* work_queue, CMSMarkStack* mark_stack, HeapWord* finger, - HeapWord** global_finger_addr, + HeapWord* volatile* global_finger_addr, ParMarkFromRootsClosure* parent); virtual void do_oop(oop* p); virtual void do_oop(narrowOop* p); diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp index 2a1be1af777..77584314dcf 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp @@ -3025,14 +3025,14 @@ class CMSConcMarkingTerminatorTerminator: public TerminatorTerminator { // MT Concurrent Marking Task class CMSConcMarkingTask: public YieldingFlexibleGangTask { - CMSCollector* _collector; - uint _n_workers; // requested/desired # workers - bool _result; - CompactibleFreeListSpace* _cms_space; - char _pad_front[64]; // padding to ... - HeapWord* _global_finger; // ... avoid sharing cache line - char _pad_back[64]; - HeapWord* _restart_addr; + CMSCollector* _collector; + uint _n_workers; // requested/desired # workers + bool _result; + CompactibleFreeListSpace* _cms_space; + char _pad_front[64]; // padding to ... + HeapWord* volatile _global_finger; // ... avoid sharing cache line + char _pad_back[64]; + HeapWord* _restart_addr; // Exposed here for yielding support Mutex* const _bit_map_lock; @@ -3068,7 +3068,7 @@ class CMSConcMarkingTask: public YieldingFlexibleGangTask { OopTaskQueue* work_queue(int i) { return task_queues()->queue(i); } - HeapWord** global_finger_addr() { return &_global_finger; } + HeapWord* volatile* global_finger_addr() { return &_global_finger; } CMSConcMarkingTerminator* terminator() { return &_term; } @@ -6554,7 +6554,7 @@ void ParMarkFromRootsClosure::scan_oops_in_oop(HeapWord* ptr) { // Note: the local finger doesn't advance while we drain // the stack below, but the global finger sure can and will. - HeapWord** gfa = _task->global_finger_addr(); + HeapWord* volatile* gfa = _task->global_finger_addr(); ParPushOrMarkClosure pushOrMarkClosure(_collector, _span, _bit_map, _work_queue, @@ -6721,7 +6721,7 @@ ParPushOrMarkClosure::ParPushOrMarkClosure(CMSCollector* collector, OopTaskQueue* work_queue, CMSMarkStack* overflow_stack, HeapWord* finger, - HeapWord** global_finger_addr, + HeapWord* volatile* global_finger_addr, ParMarkFromRootsClosure* parent) : MetadataAwareOopClosure(collector->ref_processor()), _collector(collector), diff --git a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp index 414aaa7a9c9..8a9d2b8ded3 100644 --- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp +++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp @@ -540,7 +540,7 @@ class CMSCollector: public CHeapObj { // Overflow list of grey objects, threaded through mark-word // Manipulated with CAS in the parallel/multi-threaded case. - oop _overflow_list; + oopDesc* volatile _overflow_list; // The following array-pair keeps track of mark words // displaced for accommodating overflow list above. // This code will likely be revisited under RFE#4922830. @@ -724,12 +724,12 @@ class CMSCollector: public CHeapObj { // Support for parallelizing young gen rescan in CMS remark phase ParNewGeneration* _young_gen; - HeapWord** _top_addr; // ... Top of Eden - HeapWord** _end_addr; // ... End of Eden - Mutex* _eden_chunk_lock; - HeapWord** _eden_chunk_array; // ... Eden partitioning array - size_t _eden_chunk_index; // ... top (exclusive) of array - size_t _eden_chunk_capacity; // ... max entries in array + HeapWord* volatile* _top_addr; // ... Top of Eden + HeapWord** _end_addr; // ... End of Eden + Mutex* _eden_chunk_lock; + HeapWord** _eden_chunk_array; // ... Eden partitioning array + size_t _eden_chunk_index; // ... top (exclusive) of array + size_t _eden_chunk_capacity; // ... max entries in array // Support for parallelizing survivor space rescan HeapWord** _survivor_chunk_array; diff --git a/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp b/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp index 94ec916357c..0576e05cebd 100644 --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -323,7 +323,7 @@ class ParNewGeneration: public DefNewGeneration { // A list of from-space images of to-be-scanned objects, threaded through // klass-pointers (klass information already copied to the forwarded // image.) Manipulated with CAS. - oop _overflow_list; + oopDesc* volatile _overflow_list; NOT_PRODUCT(ssize_t _num_par_pushes;) // This closure is used by the reference processor to filter out diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index 9ffbaeaad8b..8179b6e3062 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -2474,8 +2474,16 @@ size_t G1CollectedHeap::max_capacity() const { } jlong G1CollectedHeap::millis_since_last_gc() { - // assert(false, "NYI"); - return 0; + // See the notes in GenCollectedHeap::millis_since_last_gc() + // for more information about the implementation. + jlong ret_val = (os::javaTimeNanos() / NANOSECS_PER_MILLISEC) - + _g1_policy->collection_pause_end_millis(); + if (ret_val < 0) { + log_warning(gc)("millis_since_last_gc() would return : " JLONG_FORMAT + ". returning zero instead.", ret_val); + return 0; + } + return ret_val; } void G1CollectedHeap::prepare_for_verify() { diff --git a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp index 803c1b62d79..68200527033 100644 --- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp @@ -66,7 +66,8 @@ G1DefaultPolicy::G1DefaultPolicy() : _phase_times(new G1GCPhaseTimes(ParallelGCThreads)), _tenuring_threshold(MaxTenuringThreshold), _max_survivor_regions(0), - _survivors_age_table(true) { } + _survivors_age_table(true), + _collection_pause_end_millis(os::javaTimeNanos() / NANOSECS_PER_MILLISEC) { } G1DefaultPolicy::~G1DefaultPolicy() { delete _ihop_control; @@ -575,6 +576,8 @@ void G1DefaultPolicy::record_collection_pause_end(double pause_time_ms, size_t c record_pause(young_gc_pause_kind(), end_time_sec - pause_time_ms / 1000.0, end_time_sec); + _collection_pause_end_millis = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; + last_pause_included_initial_mark = collector_state()->during_initial_mark_pause(); if (last_pause_included_initial_mark) { record_concurrent_mark_init_end(0.0); diff --git a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp index 6eba7e76e20..658754e7e0e 100644 --- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp +++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp @@ -64,6 +64,8 @@ class G1DefaultPolicy: public G1Policy { double _full_collection_start_sec; + jlong _collection_pause_end_millis; + uint _young_list_target_length; uint _young_list_fixed_length; @@ -237,6 +239,8 @@ public: double reclaimable_bytes_perc(size_t reclaimable_bytes) const; + jlong collection_pause_end_millis() { return _collection_pause_end_millis; } + private: // Sets up marking if proper conditions are met. void maybe_start_marking(); diff --git a/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp b/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp index 996a68ae39c..9b74d50a085 100644 --- a/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp +++ b/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp @@ -81,47 +81,6 @@ G1StaticIHOPControl::G1StaticIHOPControl(double ihop_percent) : _last_marking_length_s(0.0) { } -#ifndef PRODUCT -static void test_update(G1IHOPControl* ctrl, double alloc_time, size_t alloc_amount, size_t young_size, double mark_time) { - for (int i = 0; i < 100; i++) { - ctrl->update_allocation_info(alloc_time, alloc_amount, young_size); - ctrl->update_marking_length(mark_time); - } -} - -void G1StaticIHOPControl::test() { - size_t const initial_ihop = 45; - - G1StaticIHOPControl ctrl(initial_ihop); - ctrl.update_target_occupancy(100); - - size_t threshold = ctrl.get_conc_mark_start_threshold(); - assert(threshold == initial_ihop, - "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold); - - ctrl.update_allocation_info(100.0, 100, 100); - threshold = ctrl.get_conc_mark_start_threshold(); - assert(threshold == initial_ihop, - "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold); - - ctrl.update_marking_length(1000.0); - threshold = ctrl.get_conc_mark_start_threshold(); - assert(threshold == initial_ihop, - "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold); - - // Whatever we pass, the IHOP value must stay the same. - test_update(&ctrl, 2, 10, 10, 3); - threshold = ctrl.get_conc_mark_start_threshold(); - assert(threshold == initial_ihop, - "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold); - - test_update(&ctrl, 12, 10, 10, 3); - threshold = ctrl.get_conc_mark_start_threshold(); - assert(threshold == initial_ihop, - "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_ihop, threshold); -} -#endif - G1AdaptiveIHOPControl::G1AdaptiveIHOPControl(double ihop_percent, G1Predictions const* predictor, size_t heap_reserve_percent, @@ -224,79 +183,3 @@ void G1AdaptiveIHOPControl::send_trace_event(G1NewTracer* tracer) { _predictor->get_new_prediction(&_marking_times_s), have_enough_data_for_prediction()); } - -#ifndef PRODUCT -void G1AdaptiveIHOPControl::test() { - size_t const initial_threshold = 45; - size_t const young_size = 10; - size_t const target_size = 100; - - // The final IHOP value is always - // target_size - (young_size + alloc_amount/alloc_time * marking_time) - - G1Predictions pred(0.95); - G1AdaptiveIHOPControl ctrl(initial_threshold, &pred, 0, 0); - ctrl.update_target_occupancy(target_size); - - // First "load". - size_t const alloc_time1 = 2; - size_t const alloc_amount1 = 10; - size_t const marking_time1 = 2; - size_t const settled_ihop1 = target_size - (young_size + alloc_amount1/alloc_time1 * marking_time1); - - size_t threshold; - threshold = ctrl.get_conc_mark_start_threshold(); - assert(threshold == initial_threshold, - "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_threshold, threshold); - for (size_t i = 0; i < G1AdaptiveIHOPNumInitialSamples - 1; i++) { - ctrl.update_allocation_info(alloc_time1, alloc_amount1, young_size); - ctrl.update_marking_length(marking_time1); - // Not enough data yet. - threshold = ctrl.get_conc_mark_start_threshold(); - assert(threshold == initial_threshold, - "Expected IHOP threshold of " SIZE_FORMAT " but is " SIZE_FORMAT, initial_threshold, threshold); - } - - test_update(&ctrl, alloc_time1, alloc_amount1, young_size, marking_time1); - - threshold = ctrl.get_conc_mark_start_threshold(); - assert(threshold == settled_ihop1, - "Expected IHOP threshold to settle at " SIZE_FORMAT " but is " SIZE_FORMAT, settled_ihop1, threshold); - - // Second "load". A bit higher allocation rate. - size_t const alloc_time2 = 2; - size_t const alloc_amount2 = 30; - size_t const marking_time2 = 2; - size_t const settled_ihop2 = target_size - (young_size + alloc_amount2/alloc_time2 * marking_time2); - - test_update(&ctrl, alloc_time2, alloc_amount2, young_size, marking_time2); - - threshold = ctrl.get_conc_mark_start_threshold(); - assert(threshold < settled_ihop1, - "Expected IHOP threshold to settle at a value lower than " SIZE_FORMAT " but is " SIZE_FORMAT, settled_ihop1, threshold); - - // Third "load". Very high (impossible) allocation rate. - size_t const alloc_time3 = 1; - size_t const alloc_amount3 = 50; - size_t const marking_time3 = 2; - size_t const settled_ihop3 = 0; - - test_update(&ctrl, alloc_time3, alloc_amount3, young_size, marking_time3); - threshold = ctrl.get_conc_mark_start_threshold(); - - assert(threshold == settled_ihop3, - "Expected IHOP threshold to settle at " SIZE_FORMAT " but is " SIZE_FORMAT, settled_ihop3, threshold); - - // And back to some arbitrary value. - test_update(&ctrl, alloc_time2, alloc_amount2, young_size, marking_time2); - - threshold = ctrl.get_conc_mark_start_threshold(); - assert(threshold > settled_ihop3, - "Expected IHOP threshold to settle at value larger than " SIZE_FORMAT " but is " SIZE_FORMAT, settled_ihop3, threshold); -} - -void IHOP_test() { - G1StaticIHOPControl::test(); - G1AdaptiveIHOPControl::test(); -} -#endif diff --git a/hotspot/src/share/vm/gc/g1/g1IHOPControl.hpp b/hotspot/src/share/vm/gc/g1/g1IHOPControl.hpp index 300884b6c2f..c8018949b39 100644 --- a/hotspot/src/share/vm/gc/g1/g1IHOPControl.hpp +++ b/hotspot/src/share/vm/gc/g1/g1IHOPControl.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,10 +99,6 @@ class G1StaticIHOPControl : public G1IHOPControl { assert(marking_length_s > 0.0, "Marking length must be larger than zero but is %.3f", marking_length_s); _last_marking_length_s = marking_length_s; } - -#ifndef PRODUCT - static void test(); -#endif }; // This algorithm tries to return a concurrent mark starting occupancy value that @@ -148,9 +144,6 @@ class G1AdaptiveIHOPControl : public G1IHOPControl { virtual void print(); virtual void send_trace_event(G1NewTracer* tracer); -#ifndef PRODUCT - static void test(); -#endif }; #endif // SHARE_VM_GC_G1_G1IHOPCONTROL_HPP diff --git a/hotspot/src/share/vm/gc/g1/g1Policy.hpp b/hotspot/src/share/vm/gc/g1/g1Policy.hpp index 92aa6050e70..ec1ea47abb9 100644 --- a/hotspot/src/share/vm/gc/g1/g1Policy.hpp +++ b/hotspot/src/share/vm/gc/g1/g1Policy.hpp @@ -119,6 +119,8 @@ public: virtual void record_full_collection_start() = 0; virtual void record_full_collection_end() = 0; + virtual jlong collection_pause_end_millis() = 0; + // Must currently be called while the world is stopped. virtual void record_concurrent_mark_init_end(double mark_init_elapsed_time_ms) = 0; diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp index 4e4bb9904cf..ccb8fbdd2fd 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp @@ -668,20 +668,18 @@ bool G1RemSet::refine_card(jbyte* card_ptr, // fail arbitrarily). We tell the iteration code to perform this // filtering when it has been determined that there has been an actual // allocation in this region and making it safe to check the young type. - bool filter_young = true; - HeapWord* stop_point = + bool card_processed = r->oops_on_card_seq_iterate_careful(dirtyRegion, &filter_then_update_rs_oop_cl, - filter_young, card_ptr); - // If stop_point is non-null, then we encountered an unallocated region - // (perhaps the unfilled portion of a TLAB.) For now, we'll dirty the - // card and re-enqueue: if we put off the card until a GC pause, then the - // unallocated portion will be filled in. Alternatively, we might try - // the full complexity of the technique used in "regular" precleaning. - if (stop_point != NULL) { + // If unable to process the card then we encountered an unparsable + // part of the heap (e.g. a partially allocated object). Redirty + // and re-enqueue: if we put off the card until a GC pause, then the + // allocation will have completed. + if (!card_processed) { + assert(!_g1->is_gc_active(), "Unparsable heap during GC"); // The card might have gotten re-dirtied and re-enqueued while we // worked. (In fact, it's pretty likely.) if (*card_ptr != CardTableModRefBS::dirty_card_val()) { diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.cpp b/hotspot/src/share/vm/gc/g1/heapRegion.cpp index 6944bcf0c44..f2df4a3c5b8 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp @@ -352,19 +352,10 @@ void HeapRegion::note_self_forwarding_removal_end(bool during_initial_mark, _prev_marked_bytes = marked_bytes; } -HeapWord* -HeapRegion:: -oops_on_card_seq_iterate_careful(MemRegion mr, - FilterOutOfRegionClosure* cl, - bool filter_young, - jbyte* card_ptr) { - // Currently, we should only have to clean the card if filter_young - // is true and vice versa. - if (filter_young) { - assert(card_ptr != NULL, "pre-condition"); - } else { - assert(card_ptr == NULL, "pre-condition"); - } +bool HeapRegion::oops_on_card_seq_iterate_careful(MemRegion mr, + FilterOutOfRegionClosure* cl, + jbyte* card_ptr) { + assert(card_ptr != NULL, "pre-condition"); G1CollectedHeap* g1h = G1CollectedHeap::heap(); // If we're within a stop-world GC, then we might look at a card in a @@ -375,7 +366,9 @@ oops_on_card_seq_iterate_careful(MemRegion mr, } else { mr = mr.intersection(used_region()); } - if (mr.is_empty()) return NULL; + if (mr.is_empty()) { + return true; + } // Otherwise, find the obj that extends onto mr.start(). // The intersection of the incoming mr (for the card) and the @@ -384,27 +377,21 @@ oops_on_card_seq_iterate_careful(MemRegion mr, // G1CollectedHeap.cpp that allocates a new region sets the // is_young tag on the region before allocating. Thus we // safely know if this region is young. - if (is_young() && filter_young) { - return NULL; + if (is_young()) { + return true; } - assert(!is_young(), "check value of filter_young"); - // We can only clean the card here, after we make the decision that - // the card is not young. And we only clean the card if we have been - // asked to (i.e., card_ptr != NULL). - if (card_ptr != NULL) { - *card_ptr = CardTableModRefBS::clean_card_val(); - // We must complete this write before we do any of the reads below. - OrderAccess::storeload(); - } + // the card is not young. + *card_ptr = CardTableModRefBS::clean_card_val(); + // We must complete this write before we do any of the reads below. + OrderAccess::storeload(); // Cache the boundaries of the memory region in some const locals HeapWord* const start = mr.start(); HeapWord* const end = mr.end(); - // We used to use "block_start_careful" here. But we're actually happy - // to update the BOT while we do this... + // Update BOT as needed while finding start of (potential) object. HeapWord* cur = block_start(start); assert(cur <= start, "Postcondition"); @@ -416,7 +403,9 @@ oops_on_card_seq_iterate_careful(MemRegion mr, obj = oop(cur); if (obj->klass_or_null() == NULL) { // Ran into an unparseable point. - return cur; + assert(!g1h->is_gc_active(), + "Unparsable heap during GC at " PTR_FORMAT, p2i(cur)); + return false; } // Otherwise... next = cur + block_size(cur); @@ -433,7 +422,9 @@ oops_on_card_seq_iterate_careful(MemRegion mr, assert((cur + block_size(cur)) > (HeapWord*)obj, "Loop invariant"); if (obj->klass_or_null() == NULL) { // Ran into an unparseable point. - return cur; + assert(!g1h->is_gc_active(), + "Unparsable heap during GC at " PTR_FORMAT, p2i(cur)); + return false; } // Advance the current pointer. "obj" still points to the object to iterate. @@ -452,7 +443,7 @@ oops_on_card_seq_iterate_careful(MemRegion mr, } } while (cur < end); - return NULL; + return true; } // Code roots support diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.hpp b/hotspot/src/share/vm/gc/g1/heapRegion.hpp index 9542b9ffb11..7f4de70b597 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.hpp @@ -653,16 +653,17 @@ class HeapRegion: public G1ContiguousSpace { } } - // filter_young: if true and the region is a young region then we - // skip the iteration. - // card_ptr: if not NULL, and we decide that the card is not young - // and we iterate over it, we'll clean the card before we start the - // iteration. - HeapWord* - oops_on_card_seq_iterate_careful(MemRegion mr, - FilterOutOfRegionClosure* cl, - bool filter_young, - jbyte* card_ptr); + // Iterate over the card in the card designated by card_ptr, + // applying cl to all references in the region. + // mr: the memory region covered by the card. + // card_ptr: if we decide that the card is not young and we iterate + // over it, we'll clean the card before we start the iteration. + // Returns true if card was successfully processed, false if an + // unparsable part of the heap was encountered, which should only + // happen when invoked concurrently with the mutator. + bool oops_on_card_seq_iterate_careful(MemRegion mr, + FilterOutOfRegionClosure* cl, + jbyte* card_ptr); size_t recorded_rs_length() const { return _recorded_rs_length; } double predicted_elapsed_time_ms() const { return _predicted_elapsed_time_ms; } diff --git a/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp b/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp index f0887f93688..7854671bf48 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.cpp @@ -482,8 +482,9 @@ void HeapRegionManager::verify_optional() { HeapRegionClaimer::HeapRegionClaimer(uint n_workers) : _n_workers(n_workers), _n_regions(G1CollectedHeap::heap()->_hrm._allocated_heapregions_length), _claims(NULL) { assert(n_workers > 0, "Need at least one worker."); - _claims = NEW_C_HEAP_ARRAY(uint, _n_regions, mtGC); - memset(_claims, Unclaimed, sizeof(*_claims) * _n_regions); + uint* new_claims = NEW_C_HEAP_ARRAY(uint, _n_regions, mtGC); + memset(new_claims, Unclaimed, sizeof(*_claims) * _n_regions); + _claims = new_claims; } HeapRegionClaimer::~HeapRegionClaimer() { diff --git a/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp b/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp index 07c84da348b..4f8863861f2 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionManager.hpp @@ -259,9 +259,9 @@ public: // The HeapRegionClaimer is used during parallel iteration over heap regions, // allowing workers to claim heap regions, gaining exclusive rights to these regions. class HeapRegionClaimer : public StackObj { - uint _n_workers; - uint _n_regions; - uint* _claims; + uint _n_workers; + uint _n_regions; + volatile uint* _claims; static const uint Unclaimed = 0; static const uint Claimed = 1; @@ -285,4 +285,3 @@ class HeapRegionClaimer : public StackObj { bool claim_region(uint region_index); }; #endif // SHARE_VM_GC_G1_HEAPREGIONMANAGER_HPP - diff --git a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp index 9aa4da68968..7967d6cf001 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp @@ -56,7 +56,7 @@ class PerRegionTable: public CHeapObj { PerRegionTable * _collision_list_next; // Global free list of PRTs - static PerRegionTable* _free_list; + static PerRegionTable* volatile _free_list; protected: // We need access in order to union things into the base table. @@ -249,7 +249,7 @@ public: static void test_fl_mem_size(); }; -PerRegionTable* PerRegionTable::_free_list = NULL; +PerRegionTable* volatile PerRegionTable::_free_list = NULL; size_t OtherRegionsTable::_max_fine_entries = 0; size_t OtherRegionsTable::_mod_max_fine_entries_mask = 0; diff --git a/hotspot/src/share/vm/gc/g1/sparsePRT.cpp b/hotspot/src/share/vm/gc/g1/sparsePRT.cpp index 44e43465ce6..4dd00b04b38 100644 --- a/hotspot/src/share/vm/gc/g1/sparsePRT.cpp +++ b/hotspot/src/share/vm/gc/g1/sparsePRT.cpp @@ -283,7 +283,7 @@ size_t RSHashTable::mem_size() const { // ---------------------------------------------------------------------- -SparsePRT* SparsePRT::_head_expanded_list = NULL; +SparsePRT* volatile SparsePRT::_head_expanded_list = NULL; void SparsePRT::add_to_expanded_list(SparsePRT* sprt) { // We could expand multiple times in a pause -- only put on list once. diff --git a/hotspot/src/share/vm/gc/g1/sparsePRT.hpp b/hotspot/src/share/vm/gc/g1/sparsePRT.hpp index 5ea825ced8c..d19a5507be2 100644 --- a/hotspot/src/share/vm/gc/g1/sparsePRT.hpp +++ b/hotspot/src/share/vm/gc/g1/sparsePRT.hpp @@ -250,7 +250,7 @@ class SparsePRT VALUE_OBJ_CLASS_SPEC { bool should_be_on_expanded_list(); - static SparsePRT* _head_expanded_list; + static SparsePRT* volatile _head_expanded_list; public: SparsePRT(HeapRegion* hr); diff --git a/hotspot/src/share/vm/gc/parallel/mutableSpace.hpp b/hotspot/src/share/vm/gc/parallel/mutableSpace.hpp index e731edd4e11..c8bc1ef8947 100644 --- a/hotspot/src/share/vm/gc/parallel/mutableSpace.hpp +++ b/hotspot/src/share/vm/gc/parallel/mutableSpace.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ class MutableSpace: public ImmutableSpace { MemRegion _last_setup_region; size_t _alignment; protected: - HeapWord* _top; + HeapWord* volatile _top; MutableSpaceMangler* mangler() { return _mangler; } @@ -69,7 +69,7 @@ class MutableSpace: public ImmutableSpace { HeapWord* top() const { return _top; } virtual void set_top(HeapWord* value) { _top = value; } - HeapWord** top_addr() { return &_top; } + HeapWord* volatile* top_addr() { return &_top; } HeapWord** end_addr() { return &_end; } virtual void set_bottom(HeapWord* value) { _bottom = value; } diff --git a/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.hpp b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.hpp index e2794db1478..654de480817 100644 --- a/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.hpp +++ b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -175,7 +175,7 @@ class ParallelScavengeHeap : public CollectedHeap { bool supports_inline_contig_alloc() const { return !UseNUMA; } - HeapWord** top_addr() const { return !UseNUMA ? young_gen()->top_addr() : (HeapWord**)-1; } + HeapWord* volatile* top_addr() const { return !UseNUMA ? young_gen()->top_addr() : (HeapWord* volatile*)-1; } HeapWord** end_addr() const { return !UseNUMA ? young_gen()->end_addr() : (HeapWord**)-1; } void ensure_parsability(bool retire_tlabs); diff --git a/hotspot/src/share/vm/gc/parallel/psYoungGen.hpp b/hotspot/src/share/vm/gc/parallel/psYoungGen.hpp index 1b51c435a53..4ee669dad96 100644 --- a/hotspot/src/share/vm/gc/parallel/psYoungGen.hpp +++ b/hotspot/src/share/vm/gc/parallel/psYoungGen.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -162,7 +162,7 @@ class PSYoungGen : public CHeapObj { return result; } - HeapWord** top_addr() const { return eden_space()->top_addr(); } + HeapWord* volatile* top_addr() const { return eden_space()->top_addr(); } HeapWord** end_addr() const { return eden_space()->end_addr(); } // Iteration. diff --git a/hotspot/src/share/vm/gc/parallel/vmStructs_parallelgc.hpp b/hotspot/src/share/vm/gc/parallel/vmStructs_parallelgc.hpp index 65d2f092171..fdaafc20fb4 100644 --- a/hotspot/src/share/vm/gc/parallel/vmStructs_parallelgc.hpp +++ b/hotspot/src/share/vm/gc/parallel/vmStructs_parallelgc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,8 @@ #define SHARE_VM_GC_PARALLEL_VMSTRUCTS_PARALLELGC_HPP #define VM_STRUCTS_PARALLELGC(nonstatic_field, \ - static_field) \ + volatile_nonstatic_field, \ + static_field) \ \ /**********************/ \ /* Parallel GC fields */ \ @@ -40,7 +41,7 @@ nonstatic_field(ImmutableSpace, _bottom, HeapWord*) \ nonstatic_field(ImmutableSpace, _end, HeapWord*) \ \ - nonstatic_field(MutableSpace, _top, HeapWord*) \ + volatile_nonstatic_field(MutableSpace, _top, HeapWord*) \ \ nonstatic_field(PSYoungGen, _reserved, MemRegion) \ nonstatic_field(PSYoungGen, _virtual_space, PSVirtualSpace*) \ diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp index e7f96a22228..58801231438 100644 --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp @@ -512,7 +512,7 @@ size_t DefNewGeneration::contiguous_available() const { } -HeapWord** DefNewGeneration::top_addr() const { return eden()->top_addr(); } +HeapWord* volatile* DefNewGeneration::top_addr() const { return eden()->top_addr(); } HeapWord** DefNewGeneration::end_addr() const { return eden()->end_addr(); } void DefNewGeneration::object_iterate(ObjectClosure* blk) { diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp index f258491ae32..12aef0f24c2 100644 --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -225,7 +225,7 @@ protected: size_t max_survivor_size() const { return _max_survivor_size; } bool supports_inline_contig_alloc() const { return true; } - HeapWord** top_addr() const; + HeapWord* volatile* top_addr() const; HeapWord** end_addr() const; // Thread-local allocation buffers diff --git a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp index d5ae7733114..b13fa976595 100644 --- a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp @@ -350,7 +350,7 @@ class CollectedHeap : public CHeapObj { // These functions return the addresses of the fields that define the // boundaries of the contiguous allocation area. (These fields should be // physically near to one another.) - virtual HeapWord** top_addr() const { + virtual HeapWord* volatile* top_addr() const { guarantee(false, "inline contiguous allocation not supported"); return NULL; } diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp index 049b675bd51..b5cd1047beb 100644 --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp @@ -721,7 +721,7 @@ bool GenCollectedHeap::supports_inline_contig_alloc() const { return _young_gen->supports_inline_contig_alloc(); } -HeapWord** GenCollectedHeap::top_addr() const { +HeapWord* volatile* GenCollectedHeap::top_addr() const { return _young_gen->top_addr(); } @@ -1256,21 +1256,20 @@ class GenTimeOfLastGCClosure: public GenCollectedHeap::GenClosure { }; jlong GenCollectedHeap::millis_since_last_gc() { - // We need a monotonically non-decreasing time in ms but - // os::javaTimeMillis() does not guarantee monotonicity. + // javaTimeNanos() is guaranteed to be monotonically non-decreasing + // provided the underlying platform provides such a time source + // (and it is bug free). So we still have to guard against getting + // back a time later than 'now'. jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; GenTimeOfLastGCClosure tolgc_cl(now); // iterate over generations getting the oldest // time that a generation was collected generation_iterate(&tolgc_cl, false); - // javaTimeNanos() is guaranteed to be monotonically non-decreasing - // provided the underlying platform provides such a time source - // (and it is bug free). So we still have to guard against getting - // back a time later than 'now'. jlong retVal = now - tolgc_cl.time(); if (retVal < 0) { - NOT_PRODUCT(log_warning(gc)("time warp: " JLONG_FORMAT, retVal);) + log_warning(gc)("millis_since_last_gc() would return : " JLONG_FORMAT + ". returning zero instead.", retVal); return 0; } return retVal; diff --git a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp index 9a469d14f7d..2e22d47a51d 100644 --- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp @@ -184,7 +184,7 @@ public: // We may support a shared contiguous allocation area, if the youngest // generation does. bool supports_inline_contig_alloc() const; - HeapWord** top_addr() const; + HeapWord* volatile* top_addr() const; HeapWord** end_addr() const; // Perform a full collection of the heap; intended for use in implementing diff --git a/hotspot/src/share/vm/gc/shared/generation.hpp b/hotspot/src/share/vm/gc/shared/generation.hpp index d71e6a1f220..7507e7763b3 100644 --- a/hotspot/src/share/vm/gc/shared/generation.hpp +++ b/hotspot/src/share/vm/gc/shared/generation.hpp @@ -263,7 +263,7 @@ class Generation: public CHeapObj { // These functions return the addresses of the fields that define the // boundaries of the contiguous allocation area. (These fields should be // physically near to one another.) - virtual HeapWord** top_addr() const { return NULL; } + virtual HeapWord* volatile* top_addr() const { return NULL; } virtual HeapWord** end_addr() const { return NULL; } // Thread-local allocation buffers diff --git a/hotspot/src/share/vm/gc/shared/workgroup.cpp b/hotspot/src/share/vm/gc/shared/workgroup.cpp index 6df874b2510..a7f6342c634 100644 --- a/hotspot/src/share/vm/gc/shared/workgroup.cpp +++ b/hotspot/src/share/vm/gc/shared/workgroup.cpp @@ -472,23 +472,21 @@ bool SequentialSubTasksDone::valid() { } bool SequentialSubTasksDone::is_task_claimed(uint& t) { - uint* n_claimed_ptr = &_n_claimed; - t = *n_claimed_ptr; + t = _n_claimed; while (t < _n_tasks) { - jint res = Atomic::cmpxchg(t+1, n_claimed_ptr, t); + jint res = Atomic::cmpxchg(t+1, &_n_claimed, t); if (res == (jint)t) { return false; } - t = *n_claimed_ptr; + t = res; } return true; } bool SequentialSubTasksDone::all_tasks_completed() { - uint* n_completed_ptr = &_n_completed; - uint complete = *n_completed_ptr; + uint complete = _n_completed; while (true) { - uint res = Atomic::cmpxchg(complete+1, n_completed_ptr, complete); + uint res = Atomic::cmpxchg(complete+1, &_n_completed, complete); if (res == complete) { break; } diff --git a/hotspot/src/share/vm/gc/shared/workgroup.hpp b/hotspot/src/share/vm/gc/shared/workgroup.hpp index b71b3e0e23a..320652a993c 100644 --- a/hotspot/src/share/vm/gc/shared/workgroup.hpp +++ b/hotspot/src/share/vm/gc/shared/workgroup.hpp @@ -318,9 +318,9 @@ public: // enumeration type. class SubTasksDone: public CHeapObj { - uint* _tasks; + volatile uint* _tasks; uint _n_tasks; - uint _threads_completed; + volatile uint _threads_completed; #ifdef ASSERT volatile uint _claimed; #endif @@ -363,11 +363,11 @@ public: class SequentialSubTasksDone : public StackObj { protected: uint _n_tasks; // Total number of tasks available. - uint _n_claimed; // Number of tasks claimed. + volatile uint _n_claimed; // Number of tasks claimed. // _n_threads is used to determine when a sub task is done. // See comments on SubTasksDone::_n_threads uint _n_threads; // Total number of parallel threads. - uint _n_completed; // Number of completed threads. + volatile uint _n_completed; // Number of completed threads. void clear(); diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp index 3717ae061d9..1b054792532 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.cpp @@ -194,6 +194,13 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(methodHandle m) return java_lang_ref_reference_get; } + if (UseFMA) { + switch (m->intrinsic_id()) { + case vmIntrinsics::_fmaD: return java_lang_math_fmaD; + case vmIntrinsics::_fmaF: return java_lang_math_fmaF; + } + } + // Accessor method? if (m->is_getter()) { // TODO: We should have used ::is_accessor above, but fast accessors in Zero expect only getters. @@ -281,6 +288,8 @@ void AbstractInterpreter::print_method_kind(MethodKind kind) { case java_lang_math_sqrt : tty->print("java_lang_math_sqrt" ); break; case java_lang_math_log : tty->print("java_lang_math_log" ); break; case java_lang_math_log10 : tty->print("java_lang_math_log10" ); break; + case java_lang_math_fmaD : tty->print("java_lang_math_fmaD" ); break; + case java_lang_math_fmaF : tty->print("java_lang_math_fmaF" ); break; case java_util_zip_CRC32_update : tty->print("java_util_zip_CRC32_update"); break; case java_util_zip_CRC32_updateBytes : tty->print("java_util_zip_CRC32_updateBytes"); break; case java_util_zip_CRC32_updateByteBuffer : tty->print("java_util_zip_CRC32_updateByteBuffer"); break; diff --git a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp index 8ec0db7e0de..f1b8f79050b 100644 --- a/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp +++ b/hotspot/src/share/vm/interpreter/abstractInterpreter.hpp @@ -76,6 +76,8 @@ class AbstractInterpreter: AllStatic { java_lang_math_log10, // implementation of java.lang.Math.log10 (x) java_lang_math_pow, // implementation of java.lang.Math.pow (x,y) java_lang_math_exp, // implementation of java.lang.Math.exp (x) + java_lang_math_fmaF, // implementation of java.lang.Math.fma (x, y, z) + java_lang_math_fmaD, // implementation of java.lang.Math.fma (x, y, z) java_lang_ref_reference_get, // implementation of java.lang.ref.Reference.get() java_util_zip_CRC32_update, // implementation of java.util.zip.CRC32.update() java_util_zip_CRC32_updateBytes, // implementation of java.util.zip.CRC32.updateBytes() diff --git a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp index d57eb46cbf1..73de575a731 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreterGenerator.cpp @@ -239,6 +239,10 @@ void TemplateInterpreterGenerator::generate_all() { method_entry(java_lang_math_log10) method_entry(java_lang_math_exp ) method_entry(java_lang_math_pow ) + if (UseFMA) { + method_entry(java_lang_math_fmaF) + method_entry(java_lang_math_fmaD) + } method_entry(java_lang_ref_reference_get) AbstractInterpreter::initialize_method_handle_entries(); @@ -445,7 +449,9 @@ address TemplateInterpreterGenerator::generate_method_entry( case Interpreter::java_lang_math_log10 : // fall thru case Interpreter::java_lang_math_sqrt : // fall thru case Interpreter::java_lang_math_pow : // fall thru - case Interpreter::java_lang_math_exp : entry_point = generate_math_entry(kind); break; + case Interpreter::java_lang_math_exp : // fall thru + case Interpreter::java_lang_math_fmaD : // fall thru + case Interpreter::java_lang_math_fmaF : entry_point = generate_math_entry(kind); break; case Interpreter::java_lang_ref_reference_get : entry_point = generate_Reference_get_entry(); break; case Interpreter::java_util_zip_CRC32_update diff --git a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp index 3fcf7bc5f71..c66df6611d8 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp @@ -114,11 +114,11 @@ void JVMCICompiler::bootstrap(TRAPS) { JVMCIRuntime::bootstrap_finished(CHECK); } -#define CHECK_ABORT THREAD); \ +#define CHECK_EXIT THREAD); \ if (HAS_PENDING_EXCEPTION) { \ char buf[256]; \ jio_snprintf(buf, 256, "Uncaught exception at %s:%d", __FILE__, __LINE__); \ - JVMCICompiler::abort_on_pending_exception(PENDING_EXCEPTION, buf); \ + JVMCICompiler::exit_on_pending_exception(PENDING_EXCEPTION, buf); \ return; \ } \ (void)(0 @@ -133,10 +133,10 @@ void JVMCICompiler::compile_method(const methodHandle& method, int entry_bci, JV return; } - JVMCIRuntime::initialize_well_known_classes(CHECK_ABORT); + JVMCIRuntime::initialize_well_known_classes(CHECK_EXIT); HandleMark hm; - Handle receiver = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK_ABORT); + Handle receiver = JVMCIRuntime::get_HotSpotJVMCIRuntime(CHECK_EXIT); JavaValue method_result(T_OBJECT); JavaCallArguments args; @@ -202,23 +202,22 @@ CompLevel JVMCIRuntime::adjust_comp_level(methodHandle method, bool is_osr, Comp return level; } -/** - * Aborts the VM due to an unexpected exception. - */ -void JVMCICompiler::abort_on_pending_exception(Handle exception, const char* message, bool dump_core) { - Thread* THREAD = Thread::current(); +void JVMCICompiler::exit_on_pending_exception(Handle exception, const char* message) { + JavaThread* THREAD = JavaThread::current(); CLEAR_PENDING_EXCEPTION; - java_lang_Throwable::java_printStackTrace(exception, THREAD); + static volatile int report_error = 0; + if (!report_error && Atomic::cmpxchg(1, &report_error, 0) == 0) { + // Only report an error once + tty->print_raw_cr(message); + java_lang_Throwable::java_printStackTrace(exception, THREAD); + } else { + // Allow error reporting thread to print the stack trace. + os::sleep(THREAD, 200, false); + } - // Give other aborting threads to also print their stack traces. - // This can be very useful when debugging class initialization - // failures. - assert(THREAD->is_Java_thread(), "compiler threads should be Java threads"); - const bool interruptible = true; - os::sleep(THREAD, 200, interruptible); - - vm_abort(dump_core); + before_exit(THREAD); + vm_exit(-1); } // Compilation entry point for methods diff --git a/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp index d051086fb44..15e4724d482 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.hpp @@ -47,7 +47,10 @@ private: static elapsedTimer _codeInstallTimer; - static void abort_on_pending_exception(Handle exception, const char* message, bool dump_core = false); + /** + * Exits the VM due to an unexpected exception. + */ + static void exit_on_pending_exception(Handle exception, const char* message); public: JVMCICompiler(); diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp index dc19a497f5e..a88f56acf32 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp @@ -112,7 +112,7 @@ uintptr_t CompilerToVM::Data::Universe_verify_oop_bits; bool CompilerToVM::Data::_supports_inline_contig_alloc; HeapWord** CompilerToVM::Data::_heap_end_addr; -HeapWord** CompilerToVM::Data::_heap_top_addr; +HeapWord* volatile* CompilerToVM::Data::_heap_top_addr; int CompilerToVM::Data::_max_oop_map_stack_offset; jbyte* CompilerToVM::Data::cardtable_start_address; @@ -153,7 +153,7 @@ void CompilerToVM::Data::initialize() { _supports_inline_contig_alloc = Universe::heap()->supports_inline_contig_alloc(); _heap_end_addr = _supports_inline_contig_alloc ? Universe::heap()->end_addr() : (HeapWord**) -1; - _heap_top_addr = _supports_inline_contig_alloc ? Universe::heap()->top_addr() : (HeapWord**) -1; + _heap_top_addr = _supports_inline_contig_alloc ? Universe::heap()->top_addr() : (HeapWord* volatile*) -1; _max_oop_map_stack_offset = (OopMapValue::register_mask - VMRegImpl::stack2reg(0)->value()) * VMRegImpl::stack_slot_size; int max_oop_map_stack_index = _max_oop_map_stack_offset / VMRegImpl::stack_slot_size; @@ -473,9 +473,20 @@ C2V_VMENTRY(jlong, getExceptionTableStart, (JNIEnv *, jobject, jobject jvmci_met return (jlong) (address) method->exception_table_start(); C2V_END -C2V_VMENTRY(jobject, getResolvedJavaMethodAtSlot, (JNIEnv *, jobject, jclass holder_handle, jint slot)) - oop java_class = JNIHandles::resolve(holder_handle); - Klass* holder = java_lang_Class::as_Klass(java_class); +C2V_VMENTRY(jobject, asResolvedJavaMethod, (JNIEnv *, jobject, jobject executable_handle)) + oop executable = JNIHandles::resolve(executable_handle); + oop mirror = NULL; + int slot = 0; + + if (executable->klass() == SystemDictionary::reflect_Constructor_klass()) { + mirror = java_lang_reflect_Constructor::clazz(executable); + slot = java_lang_reflect_Constructor::slot(executable); + } else { + assert(executable->klass() == SystemDictionary::reflect_Method_klass(), "wrong type"); + mirror = java_lang_reflect_Method::clazz(executable); + slot = java_lang_reflect_Method::slot(executable); + } + Klass* holder = java_lang_Class::as_Klass(mirror); methodHandle method = InstanceKlass::cast(holder)->method_with_idnum(slot); oop result = CompilerToVM::get_jvmci_method(method, CHECK_NULL); return JNIHandles::make_local(THREAD, result); @@ -1518,6 +1529,17 @@ C2V_VMENTRY(int, interpreterFrameSize, (JNIEnv*, jobject, jobject bytecode_frame return size + Deoptimization::last_frame_adjust(0, callee_locals) * BytesPerWord; C2V_END +C2V_VMENTRY(void, compileToBytecode, (JNIEnv*, jobject, jobject lambda_form_handle)) + Handle lambda_form = JNIHandles::resolve_non_null(lambda_form_handle); + if (lambda_form->is_a(SystemDictionary::LambdaForm_klass())) { + TempNewSymbol compileToBytecode = SymbolTable::new_symbol("compileToBytecode", CHECK); + JavaValue result(T_VOID); + JavaCalls::call_special(&result, lambda_form, SystemDictionary::LambdaForm_klass(), compileToBytecode, vmSymbols::void_method_signature(), CHECK); + } else { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + err_msg("Unexpected type: %s", lambda_form->klass()->external_name())); + } +C2V_END #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(c2v_ ## f)) @@ -1525,6 +1547,7 @@ C2V_END #define STRING "Ljava/lang/String;" #define OBJECT "Ljava/lang/Object;" #define CLASS "Ljava/lang/Class;" +#define EXECUTABLE "Ljava/lang/reflect/Executable;" #define STACK_TRACE_ELEMENT "Ljava/lang/StackTraceElement;" #define INSTALLED_CODE "Ljdk/vm/ci/code/InstalledCode;" #define TARGET_DESCRIPTION "Ljdk/vm/ci/code/TargetDescription;" @@ -1572,7 +1595,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "getClassInitializer", CC "(" HS_RESOLVED_KLASS ")" HS_RESOLVED_METHOD, FN_PTR(getClassInitializer)}, {CC "hasFinalizableSubclass", CC "(" HS_RESOLVED_KLASS ")Z", FN_PTR(hasFinalizableSubclass)}, {CC "getMaxCallTargetOffset", CC "(J)J", FN_PTR(getMaxCallTargetOffset)}, - {CC "getResolvedJavaMethodAtSlot", CC "(" CLASS "I)" HS_RESOLVED_METHOD, FN_PTR(getResolvedJavaMethodAtSlot)}, + {CC "asResolvedJavaMethod", CC "(" EXECUTABLE ")" HS_RESOLVED_METHOD, FN_PTR(asResolvedJavaMethod)}, {CC "getResolvedJavaMethod", CC "(Ljava/lang/Object;J)" HS_RESOLVED_METHOD, FN_PTR(getResolvedJavaMethod)}, {CC "getConstantPool", CC "(Ljava/lang/Object;)" HS_CONSTANT_POOL, FN_PTR(getConstantPool)}, {CC "getResolvedJavaType", CC "(Ljava/lang/Object;JZ)" HS_RESOLVED_KLASS, FN_PTR(getResolvedJavaType)}, @@ -1599,9 +1622,9 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "flushDebugOutput", CC "()V", FN_PTR(flushDebugOutput)}, {CC "methodDataProfileDataSize", CC "(JI)I", FN_PTR(methodDataProfileDataSize)}, {CC "interpreterFrameSize", CC "(" BYTECODE_FRAME ")I", FN_PTR(interpreterFrameSize)}, + {CC "compileToBytecode", CC "(" OBJECT ")V", FN_PTR(compileToBytecode)}, }; int CompilerToVM::methods_count() { return sizeof(methods) / sizeof(JNINativeMethod); } - diff --git a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp index 364be048220..e16dae86ea3 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp @@ -58,7 +58,7 @@ class CompilerToVM { static bool _supports_inline_contig_alloc; static HeapWord** _heap_end_addr; - static HeapWord** _heap_top_addr; + static HeapWord* volatile* _heap_top_addr; static int _max_oop_map_stack_offset; static jbyte* cardtable_start_address; diff --git a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp index e9305c25aab..0c504a858dc 100644 --- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp @@ -817,16 +817,6 @@ JVM_ENTRY(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass)) } JVM_END -#define CHECK_WARN_ABORT_(message) THREAD); \ - if (HAS_PENDING_EXCEPTION) { \ - warning(message); \ - char buf[512]; \ - jio_snprintf(buf, 512, "Uncaught exception at %s:%d", __FILE__, __LINE__); \ - JVMCIRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \ - return; \ - } \ - (void)(0 - void JVMCIRuntime::shutdown(TRAPS) { if (_HotSpotJVMCIRuntime_instance != NULL) { _shutdown_called = true; diff --git a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp index 3d48df55477..65459bd4a3a 100644 --- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp +++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp @@ -69,7 +69,7 @@ \ static_field(CompilerToVM::Data, _supports_inline_contig_alloc, bool) \ static_field(CompilerToVM::Data, _heap_end_addr, HeapWord**) \ - static_field(CompilerToVM::Data, _heap_top_addr, HeapWord**) \ + static_field(CompilerToVM::Data, _heap_top_addr, HeapWord* volatile*) \ \ static_field(CompilerToVM::Data, _max_oop_map_stack_offset, int) \ \ @@ -327,8 +327,11 @@ declare_constant(JVM_ACC_FIELD_INTERNAL) \ declare_constant(JVM_ACC_FIELD_STABLE) \ declare_constant(JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE) \ + declare_preprocessor_constant("JVM_ACC_VARARGS", JVM_ACC_VARARGS) \ + declare_preprocessor_constant("JVM_ACC_BRIDGE", JVM_ACC_BRIDGE) \ + declare_preprocessor_constant("JVM_ACC_ANNOTATION", JVM_ACC_ANNOTATION) \ + declare_preprocessor_constant("JVM_ACC_ENUM", JVM_ACC_ENUM) \ declare_preprocessor_constant("JVM_ACC_SYNTHETIC", JVM_ACC_SYNTHETIC) \ - declare_preprocessor_constant("JVM_RECOGNIZED_FIELD_MODIFIERS", JVM_RECOGNIZED_FIELD_MODIFIERS) \ \ declare_constant(JVM_CONSTANT_Utf8) \ declare_constant(JVM_CONSTANT_Unicode) \ @@ -660,7 +663,8 @@ #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ declare_preprocessor_constant("VM_Version::CPU_AVX512BW", CPU_AVX512BW) \ declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) \ - declare_preprocessor_constant("VM_Version::CPU_SHA", CPU_SHA) + declare_preprocessor_constant("VM_Version::CPU_SHA", CPU_SHA) \ + declare_preprocessor_constant("VM_Version::CPU_FMA", CPU_FMA) #endif diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index 08a79f11f3b..8c64dc53540 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -179,6 +179,7 @@ void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment _classpath_entry_table_size = mapinfo->_classpath_entry_table_size; _classpath_entry_table = mapinfo->_classpath_entry_table; _classpath_entry_size = mapinfo->_classpath_entry_size; + _num_patch_mod_prefixes = ClassLoader::num_patch_mod_prefixes(); // The following fields are for sanity checks for whether this archive // will function correctly with this JVM and the bootclasspath it's @@ -911,11 +912,6 @@ bool FileMapInfo::FileMapHeader::validate() { return false; } - if (Arguments::get_patch_mod_prefix() != NULL) { - FileMapInfo::fail_continue("The shared archive file cannot be used with --patch-module."); - return false; - } - if (!Arguments::has_jimage()) { FileMapInfo::fail_continue("The shared archive file cannot be used with an exploded module build."); return false; @@ -952,6 +948,23 @@ bool FileMapInfo::FileMapHeader::validate() { return false; } + // Check if there is a mismatch in --patch-module entry counts between dump time and run time. + // More checks will be performed on individual --patch-module entry in the + // SharedPathsMiscInfo::check() function. + GrowableArray* patch_mod_args = Arguments::get_patch_mod_prefix(); + if (patch_mod_args != NULL) { + if (_num_patch_mod_prefixes == 0) { + FileMapInfo::fail_stop("--patch-module found in run time but none was specified in dump time"); + } + if (patch_mod_args->length() != _num_patch_mod_prefixes) { + FileMapInfo::fail_stop("mismatched --patch-module entry counts between dump time and run time"); + } + } else { + if (_num_patch_mod_prefixes > 0) { + FileMapInfo::fail_stop("--patch-module specified in dump time but none was specified in run time"); + } + } + return true; } diff --git a/hotspot/src/share/vm/memory/filemap.hpp b/hotspot/src/share/vm/memory/filemap.hpp index baffd299436..fa1a0502ae2 100644 --- a/hotspot/src/share/vm/memory/filemap.hpp +++ b/hotspot/src/share/vm/memory/filemap.hpp @@ -155,6 +155,7 @@ public: // loading failures during runtime. int _classpath_entry_table_size; size_t _classpath_entry_size; + int _num_patch_mod_prefixes; // number of --patch-module entries SharedClassPathEntry* _classpath_entry_table; char* region_addr(int idx); diff --git a/hotspot/src/share/vm/oops/arrayOop.cpp b/hotspot/src/share/vm/oops/arrayOop.cpp deleted file mode 100644 index cd9ffcd8529..00000000000 --- a/hotspot/src/share/vm/oops/arrayOop.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" - -/////////////// Unit tests /////////////// - -#ifndef PRODUCT - -#include "oops/arrayOop.hpp" -#include "oops/oop.inline.hpp" -#include "utilities/globalDefinitions.hpp" - -bool arrayOopDesc::check_max_length_overflow(BasicType type) { - julong length = max_array_length(type); - julong bytes_per_element = type2aelembytes(type); - julong bytes = length * bytes_per_element + header_size_in_bytes(); - return (julong)(size_t)bytes == bytes; -} - -static void test_max_array_length() { - assert(arrayOopDesc::check_max_length_overflow(T_BOOLEAN), "size_t overflow for boolean array"); - assert(arrayOopDesc::check_max_length_overflow(T_CHAR), "size_t overflow for char array"); - assert(arrayOopDesc::check_max_length_overflow(T_FLOAT), "size_t overflow for float array"); - assert(arrayOopDesc::check_max_length_overflow(T_DOUBLE), "size_t overflow for double array"); - assert(arrayOopDesc::check_max_length_overflow(T_BYTE), "size_t overflow for byte array"); - assert(arrayOopDesc::check_max_length_overflow(T_SHORT), "size_t overflow for short array"); - assert(arrayOopDesc::check_max_length_overflow(T_INT), "size_t overflow for int array"); - assert(arrayOopDesc::check_max_length_overflow(T_LONG), "size_t overflow for long array"); - assert(arrayOopDesc::check_max_length_overflow(T_OBJECT), "size_t overflow for object array"); - assert(arrayOopDesc::check_max_length_overflow(T_ARRAY), "size_t overflow for array array"); - assert(arrayOopDesc::check_max_length_overflow(T_NARROWOOP), "size_t overflow for narrowOop array"); - - // T_VOID and T_ADDRESS are not supported by max_array_length() -} - -void arrayOopDesc_test() { - test_max_array_length(); -} - -#endif //PRODUCT diff --git a/hotspot/src/share/vm/oops/arrayOop.hpp b/hotspot/src/share/vm/oops/arrayOop.hpp index 8e9c2af6c8a..be439a28735 100644 --- a/hotspot/src/share/vm/oops/arrayOop.hpp +++ b/hotspot/src/share/vm/oops/arrayOop.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ class arrayOopDesc : public oopDesc { friend class VMStructs; + friend class arrayOopDescTest; // Interpreter/Compiler offsets @@ -124,10 +125,6 @@ class arrayOopDesc : public oopDesc { return (int32_t)max_elements_per_size_t; } -// for unit testing -#ifndef PRODUCT - static bool check_max_length_overflow(BasicType type); -#endif }; #endif // SHARE_VM_OOPS_ARRAYOOP_HPP diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index ea49b1baf85..1af90ceec69 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -517,7 +517,11 @@ bool InstanceKlass::link_class_or_fail(TRAPS) { bool InstanceKlass::link_class_impl( instanceKlassHandle this_k, bool throw_verifyerror, TRAPS) { - // check for error state + // check for error state. + // This is checking for the wrong state. If the state is initialization_error, + // then this class *was* linked. The CDS code does a try_link_class and uses + // initialization_error to mark classes to not include in the archive during + // DumpSharedSpaces. This should be removed when the CDS bug is fixed. if (this_k->is_in_error_state()) { ResourceMark rm(THREAD); THROW_MSG_(vmSymbols::java_lang_NoClassDefFoundError(), @@ -670,36 +674,21 @@ void InstanceKlass::link_methods(TRAPS) { // Eagerly initialize superinterfaces that declare default methods (concrete instance: any access) void InstanceKlass::initialize_super_interfaces(instanceKlassHandle this_k, TRAPS) { - if (this_k->has_default_methods()) { - for (int i = 0; i < this_k->local_interfaces()->length(); ++i) { - Klass* iface = this_k->local_interfaces()->at(i); - InstanceKlass* ik = InstanceKlass::cast(iface); - if (ik->should_be_initialized()) { - if (ik->has_default_methods()) { - ik->initialize_super_interfaces(ik, THREAD); - } - // Only initialize() interfaces that "declare" concrete methods. - // has_default_methods drives searching superinterfaces since it - // means has_default_methods in its superinterface hierarchy - if (!HAS_PENDING_EXCEPTION && ik->declares_default_methods()) { - ik->initialize(THREAD); - } - if (HAS_PENDING_EXCEPTION) { - Handle e(THREAD, PENDING_EXCEPTION); - CLEAR_PENDING_EXCEPTION; - { - EXCEPTION_MARK; - // Locks object, set state, and notify all waiting threads - this_k->set_initialization_state_and_notify( - initialization_error, THREAD); + assert (this_k->has_default_methods(), "caller should have checked this"); + for (int i = 0; i < this_k->local_interfaces()->length(); ++i) { + Klass* iface = this_k->local_interfaces()->at(i); + InstanceKlass* ik = InstanceKlass::cast(iface); - // ignore any exception thrown, superclass initialization error is - // thrown below - CLEAR_PENDING_EXCEPTION; - } - THROW_OOP(e()); - } - } + // Initialization is depth first search ie. we start with top of the inheritance tree + // has_default_methods drives searching superinterfaces since it + // means has_default_methods in its superinterface hierarchy + if (ik->has_default_methods()) { + ik->initialize_super_interfaces(ik, CHECK); + } + + // Only initialize() interfaces that "declare" concrete methods. + if (ik->should_be_initialized() && ik->declares_default_methods()) { + ik->initialize(CHECK); } } } @@ -765,32 +754,36 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) { } // Step 7 - Klass* super_klass = this_k->super(); - if (super_klass != NULL && !this_k->is_interface() && super_klass->should_be_initialized()) { - super_klass->initialize(THREAD); + // Next, if C is a class rather than an interface, initialize it's super class and super + // interfaces. + if (!this_k->is_interface()) { + Klass* super_klass = this_k->super(); + if (super_klass != NULL && super_klass->should_be_initialized()) { + super_klass->initialize(THREAD); + } + // If C implements any interfaces that declares a non-abstract, non-static method, + // the initialization of C triggers initialization of its super interfaces. + // Only need to recurse if has_default_methods which includes declaring and + // inheriting default methods + if (!HAS_PENDING_EXCEPTION && this_k->has_default_methods()) { + this_k->initialize_super_interfaces(this_k, THREAD); + } + // If any exceptions, complete abruptly, throwing the same exception as above. if (HAS_PENDING_EXCEPTION) { Handle e(THREAD, PENDING_EXCEPTION); CLEAR_PENDING_EXCEPTION; { EXCEPTION_MARK; - this_k->set_initialization_state_and_notify(initialization_error, THREAD); // Locks object, set state, and notify all waiting threads - CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, superclass initialization error is thrown below + // Locks object, set state, and notify all waiting threads + this_k->set_initialization_state_and_notify(initialization_error, THREAD); + CLEAR_PENDING_EXCEPTION; } DTRACE_CLASSINIT_PROBE_WAIT(super__failed, this_k(), -1,wait); THROW_OOP(e()); } } - // If C is an interface that declares a non-abstract, non-static method, - // the initialization of a class (not an interface) that implements C directly or - // indirectly. - // Recursively initialize any superinterfaces that declare default methods - // Only need to recurse if has_default_methods which includes declaring and - // inheriting default methods - if (!this_k->is_interface() && this_k->has_default_methods()) { - this_k->initialize_super_interfaces(this_k, CHECK); - } // Step 8 { @@ -852,10 +845,15 @@ void InstanceKlass::set_initialization_state_and_notify(ClassState state, TRAPS) void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_k, ClassState state, TRAPS) { oop init_lock = this_k->init_lock(); - ObjectLocker ol(init_lock, THREAD, init_lock != NULL); - this_k->set_init_state(state); - this_k->fence_and_clear_init_lock(); - ol.notify_all(CHECK); + if (init_lock != NULL) { + ObjectLocker ol(init_lock, THREAD); + this_k->set_init_state(state); + this_k->fence_and_clear_init_lock(); + ol.notify_all(CHECK); + } else { + assert(init_lock != NULL, "The initialization state should never be set twice"); + this_k->set_init_state(state); + } } // The embedded _implementor field can only record one implementor. diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 4953f383120..64c5c46c63e 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -734,27 +734,3 @@ bool Klass::verify_itable_index(int i) { } #endif - -/////////////// Unit tests /////////////// - -#ifndef PRODUCT - -class TestKlass { - public: - static void test_oop_is_instanceClassLoader() { - Klass* klass = SystemDictionary::ClassLoader_klass(); - guarantee(klass->is_instance_klass(), "assert"); - guarantee(InstanceKlass::cast(klass)->is_class_loader_instance_klass(), "test failed"); - - klass = SystemDictionary::String_klass(); - guarantee(!klass->is_instance_klass() || - !InstanceKlass::cast(klass)->is_class_loader_instance_klass(), - "test failed"); - } -}; - -void TestKlass_test() { - TestKlass::test_oop_is_instanceClassLoader(); -} - -#endif // PRODUCT diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp index 647cec8c83a..3bcab3c8a38 100644 --- a/hotspot/src/share/vm/oops/oop.hpp +++ b/hotspot/src/share/vm/oops/oop.hpp @@ -83,6 +83,7 @@ class oopDesc { inline Klass* klass() const; inline Klass* klass_or_null() const volatile; + inline Klass* klass_or_null_acquire() const volatile; inline Klass** klass_addr(); inline narrowKlass* compressed_klass_addr(); diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index 9a981e05c19..7697d703a1e 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -109,7 +109,6 @@ Klass* oopDesc::klass() const { } Klass* oopDesc::klass_or_null() const volatile { - // can be NULL in CMS if (UseCompressedClassPointers) { return Klass::decode_klass(_metadata._compressed_klass); } else { @@ -117,6 +116,17 @@ Klass* oopDesc::klass_or_null() const volatile { } } +Klass* oopDesc::klass_or_null_acquire() const volatile { + if (UseCompressedClassPointers) { + // Workaround for non-const load_acquire parameter. + const volatile narrowKlass* addr = &_metadata._compressed_klass; + volatile narrowKlass* xaddr = const_cast(addr); + return Klass::decode_klass(OrderAccess::load_acquire(xaddr)); + } else { + return (Klass*)OrderAccess::load_ptr_acquire(&_metadata._klass); + } +} + Klass** oopDesc::klass_addr() { // Only used internally and with CMS and will not work with // UseCompressedOops diff --git a/hotspot/src/share/vm/opto/c2compiler.cpp b/hotspot/src/share/vm/opto/c2compiler.cpp index ddbaa6b8de6..32393fc03e2 100644 --- a/hotspot/src/share/vm/opto/c2compiler.cpp +++ b/hotspot/src/share/vm/opto/c2compiler.cpp @@ -416,6 +416,12 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt case vmIntrinsics::_onSpinWait: if (!Matcher::match_rule_supported(Op_OnSpinWait)) return false; break; + case vmIntrinsics::_fmaD: + if (!UseFMA || !Matcher::match_rule_supported(Op_FmaD)) return false; + break; + case vmIntrinsics::_fmaF: + if (!UseFMA || !Matcher::match_rule_supported(Op_FmaF)) return false; + break; case vmIntrinsics::_hashCode: case vmIntrinsics::_identityHashCode: case vmIntrinsics::_getClass: diff --git a/hotspot/src/share/vm/opto/classes.hpp b/hotspot/src/share/vm/opto/classes.hpp index eab270ee399..06d754ffd78 100644 --- a/hotspot/src/share/vm/opto/classes.hpp +++ b/hotspot/src/share/vm/opto/classes.hpp @@ -151,6 +151,8 @@ macro(EncodeP) macro(EncodePKlass) macro(FastLock) macro(FastUnlock) +macro(FmaD) +macro(FmaF) macro(Goto) macro(Halt) macro(HasNegatives) diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 901f301d876..17ef1bc8c80 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -320,6 +320,7 @@ class LibraryCallKit : public GraphKit { bool inline_montgomeryMultiply(); bool inline_montgomerySquare(); bool inline_vectorizedMismatch(); + bool inline_fma(vmIntrinsics::ID id); bool inline_profileBoolean(); bool inline_isCompileConstant(); @@ -829,6 +830,10 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_hasNegatives: return inline_hasNegatives(); + case vmIntrinsics::_fmaD: + case vmIntrinsics::_fmaF: + return inline_fma(intrinsic_id()); + default: // If you get here, it may be that someone has added a new intrinsic // to the list in vmSymbols.hpp without implementing it here. @@ -6698,6 +6703,35 @@ Node* LibraryCallKit::inline_digestBase_implCompressMB_predicate(int predicate) return instof_false; // even if it is NULL } +//-------------inline_fma----------------------------------- +bool LibraryCallKit::inline_fma(vmIntrinsics::ID id) { + Node *a = NULL; + Node *b = NULL; + Node *c = NULL; + Node* result = NULL; + switch (id) { + case vmIntrinsics::_fmaD: + assert(callee()->signature()->size() == 6, "fma has 3 parameters of size 2 each."); + // no receiver since it is static method + a = round_double_node(argument(0)); + b = round_double_node(argument(2)); + c = round_double_node(argument(4)); + result = _gvn.transform(new FmaDNode(control(), a, b, c)); + break; + case vmIntrinsics::_fmaF: + assert(callee()->signature()->size() == 3, "fma has 3 parameters of size 1 each."); + a = argument(0); + b = argument(1); + c = argument(2); + result = _gvn.transform(new FmaFNode(control(), a, b, c)); + break; + default: + fatal_unexpected_iid(id); break; + } + set_result(result); + return true; +} + bool LibraryCallKit::inline_profileBoolean() { Node* counts = argument(1); const TypeAryPtr* ary = NULL; diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index 963c56fc833..7c7ed8dd493 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -2117,6 +2117,8 @@ void Matcher::find_shared( Node *n ) { case Op_StrInflatedCopy: case Op_StrCompressedCopy: case Op_EncodeISOArray: + case Op_FmaD: + case Op_FmaF: set_shared(n); // Force result into register (it will be anyways) break; case Op_ConP: { // Convert pointers above the centerline to NUL @@ -2305,6 +2307,15 @@ void Matcher::find_shared( Node *n ) { n->del_req(4); break; } + case Op_FmaD: + case Op_FmaF: { + // Restructure into a binary tree for Matching. + Node* pair = new BinaryNode(n->in(1), n->in(2)); + n->set_req(2, pair); + n->set_req(1, n->in(3)); + n->del_req(3); + break; + } default: break; } diff --git a/hotspot/src/share/vm/opto/mulnode.cpp b/hotspot/src/share/vm/opto/mulnode.cpp index fde86a85bfd..0bdde2614f3 100644 --- a/hotspot/src/share/vm/opto/mulnode.cpp +++ b/hotspot/src/share/vm/opto/mulnode.cpp @@ -1343,3 +1343,47 @@ const Type* URShiftLNode::Value(PhaseGVN* phase) const { return TypeLong::LONG; // Give up } + +//============================================================================= +//------------------------------Value------------------------------------------ +const Type* FmaDNode::Value(PhaseGVN* phase) const { + const Type *t1 = phase->type(in(1)); + if (t1 == Type::TOP) return Type::TOP; + if (t1->base() != Type::DoubleCon) return Type::DOUBLE; + const Type *t2 = phase->type(in(2)); + if (t2 == Type::TOP) return Type::TOP; + if (t2->base() != Type::DoubleCon) return Type::DOUBLE; + const Type *t3 = phase->type(in(3)); + if (t3 == Type::TOP) return Type::TOP; + if (t3->base() != Type::DoubleCon) return Type::DOUBLE; +#ifndef __STDC_IEC_559__ + return Type::DOUBLE; +#else + double d1 = t1->getd(); + double d2 = t2->getd(); + double d3 = t3->getd(); + return TypeD::make(fma(d1, d2, d3)); +#endif +} + +//============================================================================= +//------------------------------Value------------------------------------------ +const Type* FmaFNode::Value(PhaseGVN* phase) const { + const Type *t1 = phase->type(in(1)); + if (t1 == Type::TOP) return Type::TOP; + if (t1->base() != Type::FloatCon) return Type::FLOAT; + const Type *t2 = phase->type(in(2)); + if (t2 == Type::TOP) return Type::TOP; + if (t2->base() != Type::FloatCon) return Type::FLOAT; + const Type *t3 = phase->type(in(3)); + if (t3 == Type::TOP) return Type::TOP; + if (t3->base() != Type::FloatCon) return Type::FLOAT; +#ifndef __STDC_IEC_559__ + return Type::FLOAT; +#else + float f1 = t1->getf(); + float f2 = t2->getf(); + float f3 = t3->getf(); + return TypeF::make(fma(f1, f2, f3)); +#endif +} diff --git a/hotspot/src/share/vm/opto/mulnode.hpp b/hotspot/src/share/vm/opto/mulnode.hpp index 987f2e9e695..4d693970ca3 100644 --- a/hotspot/src/share/vm/opto/mulnode.hpp +++ b/hotspot/src/share/vm/opto/mulnode.hpp @@ -263,4 +263,26 @@ public: virtual uint ideal_reg() const { return Op_RegL; } }; +//------------------------------FmaDNode-------------------------------------- +// fused-multiply-add double +class FmaDNode : public Node { +public: + FmaDNode(Node *c, Node *in1, Node *in2, Node *in3) : Node(c, in1, in2, in3) {} + virtual int Opcode() const; + const Type *bottom_type() const { return Type::DOUBLE; } + virtual uint ideal_reg() const { return Op_RegD; } + virtual const Type* Value(PhaseGVN* phase) const; +}; + +//------------------------------FmaFNode-------------------------------------- +// fused-multiply-add float +class FmaFNode : public Node { +public: + FmaFNode(Node *c, Node *in1, Node *in2, Node *in3) : Node(c, in1, in2, in3) {} + virtual int Opcode() const; + const Type *bottom_type() const { return Type::FLOAT; } + virtual uint ideal_reg() const { return Op_RegF; } + virtual const Type* Value(PhaseGVN* phase) const; +}; + #endif // SHARE_VM_OPTO_MULNODE_HPP diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 549e9f47109..23575de98a8 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -562,8 +562,8 @@ JVM_ENTRY(jint, JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, } Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream)); - return StackWalk::moreFrames(stackStream_h, mode, anchor, frame_count, - start_index, frames_array_h, THREAD); + return StackWalk::fetchNextBatch(stackStream_h, mode, anchor, frame_count, + start_index, frames_array_h, THREAD); JVM_END JVM_ENTRY(void, JVM_ToStackTraceElement(JNIEnv *env, jobject frame, jobject stack)) diff --git a/hotspot/src/share/vm/prims/jvmti.xml b/hotspot/src/share/vm/prims/jvmti.xml index 48b58c3f7c7..bcbfc998567 100644 --- a/hotspot/src/share/vm/prims/jvmti.xml +++ b/hotspot/src/share/vm/prims/jvmti.xml @@ -21,7 +21,6 @@ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA or visit www.oracle.com if you need additional information or have any questions. - --> if (trace_flags) { - log_trace(jvmti)("[-] %s %s", func_name, - JvmtiUtil::error_name(JVMTI_ERROR_WRONG_PHASE)); + log_trace(jvmti)("[-] %s %s(%d)", func_name, + JvmtiUtil::error_name(JVMTI_ERROR_WRONG_PHASE), JvmtiEnv::get_phase()); } diff --git a/hotspot/src/share/vm/prims/jvmtiH.xsl b/hotspot/src/share/vm/prims/jvmtiH.xsl index 0f454a985f0..6640aa711f5 100644 --- a/hotspot/src/share/vm/prims/jvmtiH.xsl +++ b/hotspot/src/share/vm/prims/jvmtiH.xsl @@ -95,7 +95,7 @@ typedef enum { - + /* Include file for the Java(tm) Virtual Machine Tool Interface */ diff --git a/hotspot/src/share/vm/prims/jvmtiLib.xsl b/hotspot/src/share/vm/prims/jvmtiLib.xsl index 3c6a89e1ea1..fda6abc99c5 100644 --- a/hotspot/src/share/vm/prims/jvmtiLib.xsl +++ b/hotspot/src/share/vm/prims/jvmtiLib.xsl @@ -43,13 +43,56 @@ + + + + + + + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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. + + /* - - + + */ + + /* * + + + + + */ + + + + + /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */ + + /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */ diff --git a/hotspot/src/share/vm/prims/stackwalk.cpp b/hotspot/src/share/vm/prims/stackwalk.cpp index 62a0a663cad..0948e50e8be 100644 --- a/hotspot/src/share/vm/prims/stackwalk.cpp +++ b/hotspot/src/share/vm/prims/stackwalk.cpp @@ -37,42 +37,47 @@ #include "utilities/globalDefinitions.hpp" // setup and cleanup actions -void JavaFrameStream::setup_magic_on_entry(objArrayHandle frames_array) { +void BaseFrameStream::setup_magic_on_entry(objArrayHandle frames_array) { frames_array->obj_at_put(magic_pos, _thread->threadObj()); _anchor = address_value(); assert(check_magic(frames_array), "invalid magic"); } -bool JavaFrameStream::check_magic(objArrayHandle frames_array) { +bool BaseFrameStream::check_magic(objArrayHandle frames_array) { oop m1 = frames_array->obj_at(magic_pos); jlong m2 = _anchor; if (m1 == _thread->threadObj() && m2 == address_value()) return true; return false; } -bool JavaFrameStream::cleanup_magic_on_exit(objArrayHandle frames_array) { +bool BaseFrameStream::cleanup_magic_on_exit(objArrayHandle frames_array) { bool ok = check_magic(frames_array); frames_array->obj_at_put(magic_pos, NULL); _anchor = 0L; return ok; } -// Returns JavaFrameStream for the current stack being traversed. +JavaFrameStream::JavaFrameStream(JavaThread* thread, int mode) + : BaseFrameStream(thread), _vfst(thread) { + _need_method_info = StackWalk::need_method_info(mode); +} + +// Returns the BaseFrameStream for the current stack being traversed. // // Parameters: // thread Current Java thread. // magic Magic value used for each stack walking // frames_array User-supplied buffers. The 0th element is reserved -// to this JavaFrameStream to use +// for this BaseFrameStream to use // -JavaFrameStream* JavaFrameStream::from_current(JavaThread* thread, jlong magic, +BaseFrameStream* BaseFrameStream::from_current(JavaThread* thread, jlong magic, objArrayHandle frames_array) { assert(thread != NULL && thread->is_Java_thread(), ""); oop m1 = frames_array->obj_at(magic_pos); if (m1 != thread->threadObj()) return NULL; if (magic == 0L) return NULL; - JavaFrameStream* stream = (JavaFrameStream*) (intptr_t) magic; + BaseFrameStream* stream = (BaseFrameStream*) (intptr_t) magic; if (!stream->is_valid_in(thread, frames_array)) return NULL; return stream; } @@ -85,7 +90,7 @@ JavaFrameStream* JavaFrameStream::from_current(JavaThread* thread, jlong magic, // // Parameters: // mode Restrict which frames to be decoded. -// JavaFrameStream stream of javaVFrames +// BaseFrameStream stream of frames // max_nframes Maximum number of frames to be filled. // start_index Start index to the user-supplied buffers. // frames_array Buffer to store Class or StackFrame in, starting at start_index. @@ -96,7 +101,7 @@ JavaFrameStream* JavaFrameStream::from_current(JavaThread* thread, jlong magic, // // Returns the number of frames whose information was transferred into the buffers. // -int StackWalk::fill_in_frames(jlong mode, JavaFrameStream& stream, +int StackWalk::fill_in_frames(jlong mode, BaseFrameStream& stream, int max_nframes, int start_index, objArrayHandle frames_array, int& end_index, TRAPS) { @@ -110,7 +115,6 @@ int StackWalk::fill_in_frames(jlong mode, JavaFrameStream& stream, int frames_decoded = 0; for (; !stream.at_end(); stream.next()) { Method* method = stream.method(); - int bci = stream.bci(); if (method == NULL) continue; @@ -129,35 +133,42 @@ int StackWalk::fill_in_frames(jlong mode, JavaFrameStream& stream, int index = end_index++; if (TraceStackWalk) { tty->print(" %d: frame method: ", index); method->print_short_name(); - tty->print_cr(" bci=%d", bci); + tty->print_cr(" bci=%d", stream.bci()); } + if (!need_method_info(mode) && get_caller_class(mode) && + index == start_index && method->caller_sensitive()) { + ResourceMark rm(THREAD); + THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), + err_msg("StackWalker::getCallerClass called from @CallerSensitive %s method", + method->name_and_sig_as_C_string())); + } // fill in StackFrameInfo and initialize MemberName - if (live_frame_info(mode)) { - assert (use_frames_array(mode), "Bad mode for get live frame"); - Handle stackFrame(frames_array->obj_at(index)); - fill_live_stackframe(stackFrame, method, bci, stream.java_frame(), CHECK_0); - } else if (need_method_info(mode)) { - assert (use_frames_array(mode), "Bad mode for get stack frame"); - Handle stackFrame(frames_array->obj_at(index)); - fill_stackframe(stackFrame, method, bci); - } else { - assert (use_frames_array(mode) == false, "Bad mode for filling in Class object"); - if (get_caller_class(mode) && index == start_index && method->caller_sensitive()) { - ResourceMark rm(THREAD); - THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), - err_msg("StackWalker::getCallerClass called from @CallerSensitive %s method", - method->name_and_sig_as_C_string())); - } - - frames_array->obj_at_put(index, method->method_holder()->java_mirror()); - } + stream.fill_frame(index, frames_array, method, CHECK_0); if (++frames_decoded >= max_nframes) break; } return frames_decoded; } -static oop create_primitive_value_instance(StackValueCollection* values, int i, TRAPS) { +// Fill in the LiveStackFrameInfo at the given index in frames_array +void LiveFrameStream::fill_frame(int index, objArrayHandle frames_array, + const methodHandle& method, TRAPS) { + Handle stackFrame(THREAD, frames_array->obj_at(index)); + fill_live_stackframe(stackFrame, method, CHECK); +} + +// Fill in the StackFrameInfo at the given index in frames_array +void JavaFrameStream::fill_frame(int index, objArrayHandle frames_array, + const methodHandle& method, TRAPS) { + if (_need_method_info) { + Handle stackFrame(THREAD, frames_array->obj_at(index)); + fill_stackframe(stackFrame, method); + } else { + frames_array->obj_at_put(index, method->method_holder()->java_mirror()); + } +} + +oop LiveFrameStream::create_primitive_value_instance(StackValueCollection* values, int i, TRAPS) { Klass* k = SystemDictionary::resolve_or_null(vmSymbols::java_lang_LiveStackFrameInfo(), CHECK_NULL); instanceKlassHandle ik (THREAD, k); @@ -228,7 +239,7 @@ static oop create_primitive_value_instance(StackValueCollection* values, int i, return (instanceOop) result.get_jobject(); } -static objArrayHandle values_to_object_array(StackValueCollection* values, TRAPS) { +objArrayHandle LiveFrameStream::values_to_object_array(StackValueCollection* values, TRAPS) { objArrayHandle empty; int length = values->size(); objArrayOop array_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), @@ -243,7 +254,7 @@ static objArrayHandle values_to_object_array(StackValueCollection* values, TRAPS return array_h; } -static objArrayHandle monitors_to_object_array(GrowableArray* monitors, TRAPS) { +objArrayHandle LiveFrameStream::monitors_to_object_array(GrowableArray* monitors, TRAPS) { int length = monitors->length(); objArrayOop array_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), length, CHECK_(objArrayHandle())); @@ -256,19 +267,19 @@ static objArrayHandle monitors_to_object_array(GrowableArray* moni } // Fill StackFrameInfo with declaringClass and bci and initialize memberName -void StackWalk::fill_stackframe(Handle stackFrame, const methodHandle& method, int bci) { +void BaseFrameStream::fill_stackframe(Handle stackFrame, const methodHandle& method) { java_lang_StackFrameInfo::set_declaringClass(stackFrame(), method->method_holder()->java_mirror()); - java_lang_StackFrameInfo::set_method_and_bci(stackFrame(), method, bci); + java_lang_StackFrameInfo::set_method_and_bci(stackFrame(), method, bci()); } // Fill LiveStackFrameInfo with locals, monitors, and expressions -void StackWalk::fill_live_stackframe(Handle stackFrame, const methodHandle& method, - int bci, javaVFrame* jvf, TRAPS) { - fill_stackframe(stackFrame, method, bci); - if (jvf != NULL) { - StackValueCollection* locals = jvf->locals(); - StackValueCollection* expressions = jvf->expressions(); - GrowableArray* monitors = jvf->monitors(); +void LiveFrameStream::fill_live_stackframe(Handle stackFrame, + const methodHandle& method, TRAPS) { + fill_stackframe(stackFrame, method); + if (_jvf != NULL) { + StackValueCollection* locals = _jvf->locals(); + StackValueCollection* expressions = _jvf->expressions(); + GrowableArray* monitors = _jvf->monitors(); if (!locals->is_empty()) { objArrayHandle locals_h = values_to_object_array(locals, CHECK); @@ -315,15 +326,28 @@ oop StackWalk::walk(Handle stackStream, jlong mode, THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL); } - Klass* stackWalker_klass = SystemDictionary::StackWalker_klass(); - Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass(); + // Setup traversal onto my stack. + if (live_frame_info(mode)) { + assert (use_frames_array(mode), "Bad mode for get live frame"); + RegisterMap regMap(jt, true); + LiveFrameStream stream(jt, ®Map); + return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count, + start_index, frames_array, THREAD); + } else { + JavaFrameStream stream(jt, mode); + return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count, + start_index, frames_array, THREAD); + } +} +oop StackWalk::fetchFirstBatch(BaseFrameStream& stream, Handle stackStream, + jlong mode, int skip_frames, int frame_count, + int start_index, objArrayHandle frames_array, TRAPS) { methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method()); - // Setup traversal onto my stack. - RegisterMap regMap(jt, true); - JavaFrameStream stream(jt, ®Map); { + Klass* stackWalker_klass = SystemDictionary::StackWalker_klass(); + Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass(); while (!stream.at_end()) { InstanceKlass* ik = stream.method()->method_holder(); if (ik != stackWalker_klass && @@ -341,10 +365,7 @@ oop StackWalk::walk(Handle stackStream, jlong mode, // from the stack frame at depth == skip_frames. for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) { if (TraceStackWalk) { - tty->print(" skip "); stream.method()->print_short_name(); - tty->print_cr(" frame id: " PTR_FORMAT " pc: " PTR_FORMAT, - p2i(stream.java_frame()->fr().id()), - p2i(stream.java_frame()->fr().pc())); + tty->print(" skip "); stream.method()->print_short_name(); tty->cr(); } } } @@ -402,13 +423,13 @@ oop StackWalk::walk(Handle stackStream, jlong mode, // // Returns the end index of frame filled in the buffer. // -jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic, - int frame_count, int start_index, - objArrayHandle frames_array, - TRAPS) +jint StackWalk::fetchNextBatch(Handle stackStream, jlong mode, jlong magic, + int frame_count, int start_index, + objArrayHandle frames_array, + TRAPS) { JavaThread* jt = (JavaThread*)THREAD; - JavaFrameStream* existing_stream = JavaFrameStream::from_current(jt, magic, frames_array); + BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array); if (existing_stream == NULL) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L); } @@ -418,7 +439,7 @@ jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic, } if (TraceStackWalk) { - tty->print_cr("StackWalk::moreFrames frame_count %d existing_stream " PTR_FORMAT " start %d frames %d", + tty->print_cr("StackWalk::fetchNextBatch frame_count %d existing_stream " PTR_FORMAT " start %d frames %d", frame_count, p2i(existing_stream), start_index, frames_array->length()); } int end_index = start_index; @@ -429,7 +450,7 @@ jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic, int count = frame_count + start_index; assert (frames_array->length() >= count, "not enough space in buffers"); - JavaFrameStream& stream = (*existing_stream); + BaseFrameStream& stream = (*existing_stream); if (!stream.at_end()) { stream.next(); // advance past the last frame decoded in previous batch if (!stream.at_end()) { diff --git a/hotspot/src/share/vm/prims/stackwalk.hpp b/hotspot/src/share/vm/prims/stackwalk.hpp index 580c953b197..161a74599c3 100644 --- a/hotspot/src/share/vm/prims/stackwalk.hpp +++ b/hotspot/src/share/vm/prims/stackwalk.hpp @@ -29,31 +29,34 @@ #include "oops/oop.hpp" #include "runtime/vframe.hpp" -// -// JavaFrameStream is used by StackWalker to iterate through Java stack frames -// on the given JavaThread. -// -class JavaFrameStream : public StackObj { +// BaseFrameStream is an abstract base class for encapsulating the VM-side +// implementation of the StackWalker API. There are two concrete subclasses: +// - JavaFrameStream: +// -based on vframeStream; used in most instances +// - LiveFrameStream: +// -based on javaVFrame; used for retrieving locals/monitors/operands for +// LiveStackFrame +class BaseFrameStream : public StackObj { private: enum { magic_pos = 0 }; JavaThread* _thread; - javaVFrame* _jvf; jlong _anchor; +protected: + void fill_stackframe(Handle stackFrame, const methodHandle& method); public: - JavaFrameStream(JavaThread* thread, RegisterMap* rm) - : _thread(thread), _anchor(0L) { - _jvf = _thread->last_java_vframe(rm); - } + BaseFrameStream(JavaThread* thread) : _thread(thread), _anchor(0L) {} - javaVFrame* java_frame() { return _jvf; } - void next() { _jvf = _jvf->java_sender(); } - bool at_end() { return _jvf == NULL; } + virtual void next()=0; + virtual bool at_end()=0; - Method* method() { return _jvf->method(); } - int bci() { return _jvf->bci(); } + virtual Method* method()=0; + virtual int bci()=0; + + virtual void fill_frame(int index, objArrayHandle frames_array, + const methodHandle& method, TRAPS)=0; void setup_magic_on_entry(objArrayHandle frames_array); bool check_magic(objArrayHandle frames_array); @@ -67,35 +70,72 @@ public: return (jlong) castable_address(this); } - static JavaFrameStream* from_current(JavaThread* thread, jlong magic, objArrayHandle frames_array); + static BaseFrameStream* from_current(JavaThread* thread, jlong magic, objArrayHandle frames_array); +}; + +class JavaFrameStream : public BaseFrameStream { +private: + vframeStream _vfst; + bool _need_method_info; +public: + JavaFrameStream(JavaThread* thread, int mode); + + void next() { _vfst.next();} + bool at_end() { return _vfst.at_end(); } + + Method* method() { return _vfst.method(); } + int bci() { return _vfst.bci(); } + + void fill_frame(int index, objArrayHandle frames_array, + const methodHandle& method, TRAPS); +}; + +class LiveFrameStream : public BaseFrameStream { +private: + javaVFrame* _jvf; + + void fill_live_stackframe(Handle stackFrame, const methodHandle& method, TRAPS); + static oop create_primitive_value_instance(StackValueCollection* values, + int i, TRAPS); + static objArrayHandle monitors_to_object_array(GrowableArray* monitors, + TRAPS); + static objArrayHandle values_to_object_array(StackValueCollection* values, TRAPS); +public: + LiveFrameStream(JavaThread* thread, RegisterMap* rm) : BaseFrameStream(thread) { + _jvf = thread->last_java_vframe(rm); + } + + void next() { _jvf = _jvf->java_sender(); } + bool at_end() { return _jvf == NULL; } + + Method* method() { return _jvf->method(); } + int bci() { return _jvf->bci(); } + + void fill_frame(int index, objArrayHandle frames_array, + const methodHandle& method, TRAPS); }; class StackWalk : public AllStatic { private: - static int fill_in_frames(jlong mode, JavaFrameStream& stream, + static int fill_in_frames(jlong mode, BaseFrameStream& stream, int max_nframes, int start_index, objArrayHandle frames_array, int& end_index, TRAPS); - static void fill_stackframe(Handle stackFrame, const methodHandle& method, int bci); - - static void fill_live_stackframe(Handle stackFrame, const methodHandle& method, int bci, - javaVFrame* jvf, TRAPS); - static inline bool get_caller_class(int mode) { return (mode & JVM_STACKWALK_GET_CALLER_CLASS) != 0; } static inline bool skip_hidden_frames(int mode) { return (mode & JVM_STACKWALK_SHOW_HIDDEN_FRAMES) == 0; } - static inline bool need_method_info(int mode) { - return (mode & JVM_STACKWALK_FILL_CLASS_REFS_ONLY) == 0; - } static inline bool live_frame_info(int mode) { return (mode & JVM_STACKWALK_FILL_LIVE_STACK_FRAMES) != 0; } public: + static inline bool need_method_info(int mode) { + return (mode & JVM_STACKWALK_FILL_CLASS_REFS_ONLY) == 0; + } static inline bool use_frames_array(int mode) { return (mode & JVM_STACKWALK_FILL_CLASS_REFS_ONLY) == 0; } @@ -104,9 +144,12 @@ public: objArrayHandle frames_array, TRAPS); - static jint moreFrames(Handle stackStream, jlong mode, jlong magic, - int frame_count, int start_index, - objArrayHandle frames_array, - TRAPS); + static oop fetchFirstBatch(BaseFrameStream& stream, Handle stackStream, + jlong mode, int skip_frames, int frame_count, + int start_index, objArrayHandle frames_array, TRAPS); + + static jint fetchNextBatch(Handle stackStream, jlong mode, jlong magic, + int frame_count, int start_index, + objArrayHandle frames_array, TRAPS); }; #endif // SHARE_VM_PRIMS_STACKWALK_HPP diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index e7e45e9fcd1..8dc6519381d 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -3897,10 +3897,6 @@ jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_ void Arguments::set_shared_spaces_flags() { if (DumpSharedSpaces) { - if (Arguments::get_patch_mod_prefix() != NULL) { - vm_exit_during_initialization( - "Cannot use the following option when dumping the shared archive: --patch-module"); - } if (RequireSharedSpaces) { warning("Cannot dump shared archive while using shared archive"); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 1c20ecf1174..ec1c15f7184 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -659,6 +659,9 @@ public: product(bool, UseAES, false, \ "Control whether AES instructions can be used on x86/x64") \ \ + product(bool, UseFMA, false, \ + "Control whether FMA instructions can be used") \ + \ product(bool, UseSHA, false, \ "Control whether SHA instructions can be used " \ "on SPARC, on ARM and on x86") \ diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 84eb6fa7d86..514da115a13 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -2103,6 +2103,8 @@ typedef CompactHashtable SymbolCompactHashTable; declare_c2_type(OverflowAddLNode, OverflowLNode) \ declare_c2_type(OverflowSubLNode, OverflowLNode) \ declare_c2_type(OverflowMulLNode, OverflowLNode) \ + declare_c2_type(FmaDNode, Node) \ + declare_c2_type(FmaFNode, Node) \ \ /*********************/ \ /* Adapter Blob Entries */ \ @@ -2970,6 +2972,7 @@ VMStructEntry VMStructs::localHotSpotVMStructs[] = { #if INCLUDE_ALL_GCS VM_STRUCTS_PARALLELGC(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, + GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY) VM_STRUCTS_CMS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, @@ -2982,7 +2985,7 @@ VMStructEntry VMStructs::localHotSpotVMStructs[] = { #if INCLUDE_TRACE VM_STRUCTS_TRACE(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, - GENERATE_STATIC_VM_STRUCT_ENTRY) + GENERATE_STATIC_VM_STRUCT_ENTRY) #endif VM_STRUCTS_EXT(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, @@ -3168,11 +3171,12 @@ VMStructs::init() { #if INCLUDE_ALL_GCS VM_STRUCTS_PARALLELGC(CHECK_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_STATIC_VM_STRUCT_ENTRY); + CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY, + CHECK_STATIC_VM_STRUCT_ENTRY); VM_STRUCTS_CMS(CHECK_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_STATIC_VM_STRUCT_ENTRY); + CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY, + CHECK_STATIC_VM_STRUCT_ENTRY); VM_STRUCTS_G1(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY); @@ -3181,7 +3185,7 @@ VMStructs::init() { #if INCLUDE_TRACE VM_STRUCTS_TRACE(CHECK_NONSTATIC_VM_STRUCT_ENTRY, - CHECK_STATIC_VM_STRUCT_ENTRY); + CHECK_STATIC_VM_STRUCT_ENTRY); #endif VM_STRUCTS_EXT(CHECK_NONSTATIC_VM_STRUCT_ENTRY, @@ -3293,6 +3297,7 @@ VMStructs::init() { CHECK_NO_OP)); #if INCLUDE_ALL_GCS debug_only(VM_STRUCTS_PARALLELGC(ENSURE_FIELD_TYPE_PRESENT, + ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT)); debug_only(VM_STRUCTS_CMS(ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT, diff --git a/hotspot/src/share/vm/utilities/internalVMTests.cpp b/hotspot/src/share/vm/utilities/internalVMTests.cpp index 76087d52bfe..c132386c4e6 100644 --- a/hotspot/src/share/vm/utilities/internalVMTests.cpp +++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp @@ -52,19 +52,14 @@ void InternalVMTests::run() { run_unit_test(TestVirtualSpaceNode_test); run_unit_test(TestGlobalDefinitions_test); run_unit_test(GCTimer_test); - run_unit_test(arrayOopDesc_test); run_unit_test(CollectedHeap_test); run_unit_test(QuickSort_test); run_unit_test(GuardedMemory_test); run_unit_test(TestNewSize_test); run_unit_test(TestOldSize_test); - run_unit_test(TestKlass_test); run_unit_test(TestBitMap_test); run_unit_test(TestResourcehash_test); run_unit_test(ObjectMonitor_test); - run_unit_test(Test_linked_list); - run_unit_test(TestChunkedList_test); - run_unit_test(JSON_test); run_unit_test(Test_log_tag_combinations_limit); run_unit_test(Test_logtarget); run_unit_test(Test_logstream); @@ -82,7 +77,6 @@ void InternalVMTests::run() { run_unit_test(Test_invalid_log_file); run_unit_test(Test_multiline_logging); run_unit_test(DirectivesParser_test); - run_unit_test(Test_TempNewSymbol); #if INCLUDE_VM_STRUCTS run_unit_test(VMStructs_test); #endif @@ -91,7 +85,6 @@ void InternalVMTests::run() { run_unit_test(TestBufferingOopClosure_test); if (UseG1GC) { run_unit_test(FreeRegionList_test); - run_unit_test(IHOP_test); } run_unit_test(WorkerDataArray_test); run_unit_test(ParallelCompact_test); diff --git a/hotspot/src/share/vm/utilities/json.cpp b/hotspot/src/share/vm/utilities/json.cpp index cb3bf391006..dca08325a05 100644 --- a/hotspot/src/share/vm/utilities/json.cpp +++ b/hotspot/src/share/vm/utilities/json.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -686,286 +686,3 @@ void JSON::error(JSON_ERROR e, const char* format, ...) { } } -#ifndef PRODUCT -class JSONTest : public JSON { - public: - static void test(); - - private: - JSONTest(const char* text); - static void test(const char* json, bool valid); - - void log(uint level, const char* format, ...) ATTRIBUTE_PRINTF(3, 4); - - bool callback(JSON_TYPE t, JSON_VAL* v, uint level); - JSON_TYPE prev; -}; - -void JSON_test() { - JSONTest::test(); -} - -void JSONTest::test(const char* text, bool should_pass) { - JSONTest json(text); - if (should_pass) { - assert(json.valid() == true, "failed on a valid json string"); - if (VerboseInternalVMTests) { - tty->print_cr("-- json test passed as expected --"); - } - } else { - assert(json.valid() == false, "succeeded on an invalid json string"); - if (VerboseInternalVMTests) { - tty->print_cr("-- json test failed as expected --"); - } - } -} - -JSONTest::JSONTest(const char* text) : JSON(text, !VerboseInternalVMTests, tty) { - prev = JSON_NONE; - parse(); -} - -void JSONTest::test() { - JSONTest::test("{}", true); - JSONTest::test("[]", true); - JSONTest::test(" { } ", true); - JSONTest::test(" [ ] ", true); - - JSONTest::test("\"error\"", false); - JSONTest::test("error", false); - JSONTest::test("1", false); - JSONTest::test("1.2", false); - JSONTest::test("true", false); - JSONTest::test("false", false); - JSONTest::test("null", false); - - JSONTest::test("[ 1 ]", true); - JSONTest::test("[ 1, ]", true); - JSONTest::test("[ true ]", true); - JSONTest::test("[ true, ]", true); - JSONTest::test("[ false ]", true); - JSONTest::test("[ false, ]", true); - JSONTest::test("[ null ]", true); - JSONTest::test("[ null, ]", true); - JSONTest::test("[ \"\" ]", true); - JSONTest::test("[ \"\", ]", true); - JSONTest::test("[ \"elem1\" ]", true); - JSONTest::test("[ \"elem1\", ]", true); - JSONTest::test("[ \"elem1\", ]", true); - JSONTest::test("[ \"elem1\" ]", true); - JSONTest::test("[ \"elem1\", \"elem2\" ]", true); - JSONTest::test("[ \"elem1\", \"elem2\", ]", true); - - - JSONTest::test("[ \"elem1\" ] { }", false); - JSONTest::test("[ elem1, \"elem2\" ]", false); - JSONTest::test("[ \"elem1\"", false); - JSONTest::test("[ \"elem1 ]", false); - JSONTest::test("[ \"elem1\", \"elem2\"", false); - JSONTest::test("[ truefoo ]", false); - JSONTest::test("[ falsefoo ]", false); - JSONTest::test("[ nullfoo ]", false); - - JSONTest::test("{ key : 1 }", true); - JSONTest::test("{ key : 1, }", true); - JSONTest::test("{ key : true }", true); - JSONTest::test("{ key : true, }", true); - JSONTest::test("{ key : false }", true); - JSONTest::test("{ key : false, }", true); - JSONTest::test("{ key : null }", true); - JSONTest::test("{ key : null, }", true); - JSONTest::test("{ \"\" : \"\" }", true); - JSONTest::test("{ \"\" : \"\", }", true); - JSONTest::test("{ \"key1\" : \"val1\" }", true); - JSONTest::test("{ \"key1\" : \"val1\", }", true); - JSONTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\" }", true); - JSONTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\", }", true); - - JSONTest::test("{ \"key\" : \"val\" } [ \"error\" ]", false); - JSONTest::test("{ \"key\" : \"val\" ", false); - - JSONTest::test("/**/ { }", true); - JSONTest::test("/* */ { }", true); - JSONTest::test("/*foo*/ { }", true); - JSONTest::test("/* *foo */ { }", true); - JSONTest::test("/* *foo* */ { }", true); - JSONTest::test("/* /*foo */ { }", true); - JSONTest::test("{ } /* foo */", true); - JSONTest::test("{ } /* foo */ ", true); - JSONTest::test("{ } //", true); - JSONTest::test("{ } // ", true); - JSONTest::test("{ } // foo", true); - - JSONTest::test("/* * / { }", false); - JSONTest::test("/ * */ { }", false); - JSONTest::test("// { }", false); - JSONTest::test("/* { } */", false); - JSONTest::test("/* { } */ ", false); - JSONTest::test("/* { } ", false); - JSONTest::test("{ } /* ", false); - JSONTest::test("/* { } *", false); - JSONTest::test("{ /* } */", false); - JSONTest::test("[ /* ] */", false); - JSONTest::test("{ key : \"val\", /* } */", false); - JSONTest::test("[ \"val\", /* ] */", false); - - JSONTest::test("/* comment */{ key1 : { \"key2\" : { \"key3\" : [ \"elem1\", \"elem2\", { \"key4\" : null }, 3 , 2 , 1 , 0 , -1 , -2 , -3 , true, false, null, ] }, \"key5\" : true }, \"key6\" : [ \"☃\" ], key7 : \"val\",}", true); - JSONTest::test("/* comment */ { \"key1\" : { \"key2\" : { \"key3\" : [ \"elem1\", \"elem2\", { \"key4\" : null }, 3 , 2 , 1 , 0 , -1 , -2 , -3 , true, false, null, ] }, \"key5\" : true }, \"key6\" : [ \"☃\" ], key7 : \"val\",}", true); - JSONTest::test("/*comment*/{\"ff1 fsd\":{\"☃\":{\"☃\":[\"☃\",\"☃\"]},\"☃\":true},\"☃\":[\"☃\"],\"foo\":\"☃\",}", true); - JSONTest::test("/* comment */ { key1 error : { \"☃\" : { \"☃\" : [ \"☃\", \"☃\" ] }, \"☃\" : true }, \"baz\" : [ \"☃\" ], foo : \"☃\",}", false); // first key needs to be quoted since it contains a space - - - JSONTest::test("[\n]", true); - - JSONTest::test( - "[" "\n" - " {" - " // pattern to match against class+method+signature" "\n" - " // leading and trailing wildcard (*) allowed" "\n" - " match: \"foo.bar.*\"," "\n" - " " "\n" - " // override defaults for specified compiler" "\n" - " // we may differentiate between levels too. TBD." "\n" - " c1: {" "\n" - " //override c1 presets " "\n" - " array_bounds_check_removal: false" "\n" - " }," "\n" - "" "\n" - " c2: {" "\n" - " // control inlining of method" "\n" - " // + force inline, - dont inline" "\n" - " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n" - " }," "\n" - "" "\n" - " // directives outside a specific preset applies to all compilers" "\n" - " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n" - " print_assembly: true," "\n" - " verify_oopmaps: true," "\n" - " max_loop_unrolling: 5" "\n" - " }," "\n" - " {" "\n" - " // matching several patterns require an array" "\n" - " match: [\"baz.*\",\"frob*\"]," "\n" - "" "\n" - " // only enable c1 for this directive" "\n" - " // all enabled by default. Command disables all not listed" "\n" - " enable: \"c1\"," "\n" - "" "\n" - " // applies to all compilers" "\n" - " // + force inline, - dont inline" "\n" - " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n" - " print_inlining: true," "\n" - "" "\n" - " // force matching compiles to be blocking/syncronous" "\n" - " blocking_compile: true" "\n" - " }," "\n" - "]" "\n", true); -} - -void JSONTest::log(uint indent, const char* format, ...) { - if (VerboseInternalVMTests) { - if (prev != JSON_KEY) { - for (uint i = 0; i < indent; i++) { - _st->print(" "); - } - } - va_list args; - va_start(args, format); - _st->vprint(format, args); - va_end(args); - } -} - -bool JSONTest::callback(JSON_TYPE t, JSON_VAL* v, uint rlevel) { - switch (t) { - case JSON_OBJECT_BEGIN: - log(rlevel, "{\n"); - prev = JSON_NONE; // Only care about JSON_KEY, to indent correctly - return true; - - case JSON_OBJECT_END: - log(rlevel, "},\n"); - prev = JSON_NONE; - return true; - - case JSON_ARRAY_BEGIN: - log(rlevel, "[\n"); - prev = JSON_NONE; - return true; - - case JSON_ARRAY_END: - log(rlevel, "],\n"); - prev = JSON_NONE; - return true; - - case JSON_KEY: - if (VerboseInternalVMTests) { - for (uint i = 0; i < rlevel; i++) { - _st->print(" "); - } - _st->print(""); - for (size_t i = 0; i < v->str.length; i++) { - u_char c = v->str.start[i]; - assert(c != 0, "string overrun"); - if (c == 0) { - return false; - } - _st->print("%c", c); - } - _st->print(" : "); - } - prev = JSON_KEY; - return true; - - case JSON_STRING: - if (VerboseInternalVMTests) { - if (prev != JSON_KEY) { - for (uint i = 0; i < rlevel; i++) { - _st->print(" "); - } - } - _st->print(""); - for (size_t i = 0; i < v->str.length; i++) { - u_char c = v->str.start[i]; - assert(c != 0, "string overrun"); - if (c == 0) { - return false; - } - _st->print("%c", c); - } - _st->print(",\n"); - } - prev = JSON_NONE; - return true; - - case JSON_NUMBER_INT: - log(rlevel, "%" PRId64 ",\n", v->int_value); - prev = JSON_NONE; - return true; - - case JSON_NUMBER_FLOAT: - log(rlevel, "%lf,\n", v->double_value); - prev = JSON_NONE; - return true; - - case JSON_TRUE: - log(rlevel, ",\n"); - prev = JSON_NONE; - return true; - - case JSON_FALSE: - log(rlevel, ",\n"); - prev = JSON_NONE; - return true; - - case JSON_NULL: - log(rlevel, ",\n"); - prev = JSON_NONE; - return true; - - default: - error(INTERNAL_ERROR, "unknown JSON type"); - return false; - } -} -#endif diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index fc1eae68feb..74658bc86af 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -351,16 +351,29 @@ hotspot_fast_gc_gcold = \ hotspot_fast_runtime = \ runtime/ \ + -runtime/6626217/Test6626217.sh \ + -runtime/7100935 \ + -runtime/7158988/FieldMonitor.java \ + -runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java \ + -runtime/CommandLine/PrintGCApplicationConcurrentTime.java \ + -runtime/ConstantPool/IntfMethod.java \ + -runtime/ErrorHandling/CreateCoredumpOnCrash.java \ -runtime/ErrorHandling/ErrorHandler.java \ - -runtime/RedefineObject/TestRedefineObject.java \ - -runtime/MirrorFrame/Test8003720.java \ - -runtime/Metaspace/FragmentMetaspace.java \ - -runtime/Metaspace/FragmentMetaspaceSimple.java \ - -runtime/Thread/TestThreadDumpMonitorContention.java \ - -runtime/SharedArchiveFile/SharedBaseAddress.java \ + -runtime/logging/MonitorMismatchTest.java \ -runtime/memory/ReserveMemory.java \ -runtime/memory/RunUnitTestsConcurrently.java \ - -runtime/Unsafe/RangeCheck.java \ + -runtime/Metaspace/FragmentMetaspace.java \ + -runtime/Metaspace/FragmentMetaspaceSimple.java \ + -runtime/MirrorFrame/Test8003720.java \ + -runtime/modules/LoadUnloadModuleStress.java \ + -runtime/modules/ModuleStress/ExportModuleStressTest.java \ + -runtime/modules/ModuleStress/ModuleStressGC.java \ + -runtime/NMT \ + -runtime/RedefineObject/TestRedefineObject.java \ + -runtime/RedefineTests/RedefinePreviousVersions.java \ + -runtime/RedefineTests/RedefineRunningMethods.java \ + -runtime/RedefineTests/RedefineRunningMethodsWithBacktrace.java \ + -runtime/ReservedStack \ -runtime/SelectionResolution/AbstractMethodErrorTest.java \ -runtime/SelectionResolution/IllegalAccessErrorTest.java \ -runtime/SelectionResolution/InvokeInterfaceICCE.java \ @@ -372,14 +385,14 @@ hotspot_fast_runtime = \ -runtime/SelectionResolution/InvokeVirtualSuccessTest.java \ -runtime/SharedArchiveFile/CdsSameObjectAlignment.java \ -runtime/SharedArchiveFile/DefaultUseWithClient.java \ + -runtime/SharedArchiveFile/SharedBaseAddress.java \ -runtime/Thread/CancellableThreadTest.java \ - -runtime/7158988/FieldMonitor.java \ - -runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java \ + -runtime/Thread/TestThreadDumpMonitorContention.java \ + -runtime/Unsafe/RangeCheck.java \ sanity/ \ testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java hotspot_fast_serviceability = \ - sanity/ExecuteInternalVMTests.java \ serviceability/dcmd/compiler \ serviceability/logging @@ -398,6 +411,8 @@ hotspot_jprt = \ hotspot_runtime_tier2 = \ runtime/ \ serviceability/ \ + -runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java \ + -runtime/Thread/TestThreadDumpMonitorContention.java \ -:hotspot_fast_runtime \ -:hotspot_fast_serviceability \ -:hotspot_runtime_tier2_platform_agnostic @@ -405,6 +420,14 @@ hotspot_runtime_tier2 = \ hotspot_runtime_tier2_platform_agnostic = \ runtime/SelectionResolution \ -:hotspot_fast_runtime + +hotspot_runtime_tier3 = \ + runtime/ \ + serviceability/ \ + -:hotspot_fast_runtime \ + -:hotspot_fast_serviceability \ + -:hotspot_runtime_tier2_platform_agnostic \ + -:hotspot_runtime_tier2 hotspot_runtime_minimalvm = \ runtime/MinimalVM \ diff --git a/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java b/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java index 95899878e81..c831ffc6782 100644 --- a/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java +++ b/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java @@ -29,7 +29,7 @@ * @modules java.base/jdk.internal.misc * java.management * - * @ignore 8071905 + * @ignore 8166554 * @build sun.hotspot.WhiteBox * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/compilercontrol/share/processors/LogProcessor.java b/hotspot/test/compiler/compilercontrol/share/processors/LogProcessor.java index 98fce874cb1..a926c7db560 100644 --- a/hotspot/test/compiler/compilercontrol/share/processors/LogProcessor.java +++ b/hotspot/test/compiler/compilercontrol/share/processors/LogProcessor.java @@ -74,7 +74,7 @@ public class LogProcessor implements Consumer { if (loggedMethods.isEmpty()) { return; } - matchTasks(getScanner()); + matchTasks(); } /* @@ -95,19 +95,21 @@ public class LogProcessor implements Consumer { * Parses for <task method='java.lang.String indexOf (I)I' > * and finds if there is a compilation log for this task */ - private void matchTasks(Scanner scanner) { - String task = scanner.findWithinHorizon(TASK_ELEMENT, 0); - while (task != null) { - String element = scanner.findWithinHorizon(ANY_ELEMENT, 0); - if (Pattern.matches(TASK_DONE_ELEMENT, element) - || Pattern.matches(TASK_END_ELEMENT, element)) { - /* If there is nothing between and - except then compilation log is empty. - Check the method in this task should not be logged */ - Asserts.assertFalse(matchMethod(task), "Compilation log " - + "expected. Met: " + element); - } - task = scanner.findWithinHorizon(TASK_ELEMENT, 0); + private void matchTasks() { + try (Scanner scanner = getScanner()) { + String task = scanner.findWithinHorizon(TASK_ELEMENT, 0); + while (task != null) { + String element = scanner.findWithinHorizon(ANY_ELEMENT, 0); + if (Pattern.matches(TASK_DONE_ELEMENT, element) + || Pattern.matches(TASK_END_ELEMENT, element)) { + /* If there is nothing between and + except then compilation log is empty. + Check the method in this task should not be logged */ + Asserts.assertFalse(matchMethod(task), "Compilation log " + + "expected. Met: " + element); + } + task = scanner.findWithinHorizon(TASK_ELEMENT, 0); + } } } diff --git a/hotspot/test/compiler/jsr292/NullConstantReceiver.java b/hotspot/test/compiler/jsr292/NullConstantReceiver.java index 47da7d54414..369c7245034 100644 --- a/hotspot/test/compiler/jsr292/NullConstantReceiver.java +++ b/hotspot/test/compiler/jsr292/NullConstantReceiver.java @@ -23,10 +23,11 @@ /** * @test - * @bug 8059556 8158639 + * @bug 8059556 8158639 8164508 * * @run main/othervm -Xbatch compiler.jsr292.NullConstantReceiver * @run main/othervm -Xbatch -XX:CompileCommand=exclude,*::run compiler.jsr292.NullConstantReceiver + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,*::run compiler.jsr292.NullConstantReceiver */ package compiler.jsr292; diff --git a/hotspot/test/compiler/jvmci/common/CTVMUtilities.java b/hotspot/test/compiler/jvmci/common/CTVMUtilities.java index 03335f6f59a..7ba6d00debf 100644 --- a/hotspot/test/compiler/jvmci/common/CTVMUtilities.java +++ b/hotspot/test/compiler/jvmci/common/CTVMUtilities.java @@ -57,18 +57,7 @@ public class CTVMUtilities { if (!(method instanceof Method || method instanceof Constructor)) { throw new Error("wrong executable type " + method.getClass()); } - Field slotField; - int slot; - try { - slotField = method.getClass().getDeclaredField("slot"); - boolean old = slotField.isAccessible(); - slotField.setAccessible(true); - slot = slotField.getInt(method); - slotField.setAccessible(old); - } catch (ReflectiveOperationException e) { - throw new Error("TEST BUG: Can't get slot field", e); - } - return CompilerToVMHelper.getResolvedJavaMethodAtSlot(cls, slot); + return CompilerToVMHelper.asResolvedJavaMethod(method); } public static HotSpotResolvedJavaMethod getResolvedMethod( diff --git a/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java b/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java index 2985ed89a94..1fa24207d63 100644 --- a/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java +++ b/hotspot/test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java @@ -28,6 +28,7 @@ import jdk.vm.ci.code.InvalidInstalledCodeException; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.ResolvedJavaMethod; +import java.lang.reflect.Executable; /** * A simple "proxy" class to get test access to CompilerToVM package-private methods @@ -171,9 +172,9 @@ public class CompilerToVMHelper { return CTVM.hasFinalizableSubclass((HotSpotResolvedObjectTypeImpl) type); } - public static HotSpotResolvedJavaMethodImpl getResolvedJavaMethodAtSlot( - Class holder, int slot) { - return CTVM.getResolvedJavaMethodAtSlot(holder, slot); + public static HotSpotResolvedJavaMethodImpl asResolvedJavaMethod( + Executable executable) { + return CTVM.asResolvedJavaMethod(executable); } public static long getMaxCallTargetOffset(long address) { diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java b/hotspot/test/compiler/jvmci/compilerToVM/AsResolvedJavaMethodTest.java similarity index 61% rename from hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java rename to hotspot/test/compiler/jvmci/compilerToVM/AsResolvedJavaMethodTest.java index 49a6e3826bf..1234edb4cd6 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/AsResolvedJavaMethodTest.java @@ -36,7 +36,7 @@ * jdk.vm.ci/jdk.vm.ci.meta * @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI - * compiler.jvmci.compilerToVM.GetResolvedJavaMethodAtSlotTest + * compiler.jvmci.compilerToVM.AsResolvedJavaMethodTest */ package compiler.jvmci.compilerToVM; @@ -45,10 +45,12 @@ import jdk.test.lib.Asserts; import jdk.vm.ci.hotspot.CompilerToVMHelper; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import java.util.HashMap; -import java.util.Map; +import java.lang.reflect.Executable; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; -public class GetResolvedJavaMethodAtSlotTest { +public class AsResolvedJavaMethodTest { private static class A { { @@ -81,41 +83,31 @@ public class GetResolvedJavaMethodAtSlotTest { } public static void main(String[] args) { - Map, Integer> testCases = getTestCases(); - testCases.forEach(GetResolvedJavaMethodAtSlotTest::test); + List> testCases = getTestCases(); + testCases.forEach(AsResolvedJavaMethodTest::test); } - private static Map, Integer> getTestCases() { - Map, Integer> testCases = new HashMap<>(); - testCases.put(A.class, 5); // ctor, init, f1, f2, f3 - testCases.put(S.class, 5); // ctor, cinit, f1, f2, f3 - testCases.put(I.class, 3); // f1, f2, f3 - testCases.put(B.class, 2); // ctor, f4 + private static List> getTestCases() { + List> testCases = new ArrayList<>(); + testCases.add(A.class); + testCases.add(S.class); + testCases.add(I.class); + testCases.add(B.class); return testCases; } - private static void test(Class aClass, int methodNumber) { - testSlotBigger(aClass); - testCorrectMethods(aClass, methodNumber); + private static void test(Class aClass) { + testCorrectMethods(aClass); } - private static void testSlotBigger(Class holder) { - HotSpotResolvedJavaMethod method - = CompilerToVMHelper.getResolvedJavaMethodAtSlot(holder, 50); - Asserts.assertNull(method, "Got method for non existing slot 50 in " - + holder); - } - - private static void testCorrectMethods(Class holder, int methodsNumber) { - for (int i = 0; i < methodsNumber; i++) { - String caseName = String.format("slot %d in %s", - i, holder.getCanonicalName()); + private static void testCorrectMethods(Class holder) { + List executables = new ArrayList<>(); + executables.addAll(Arrays.asList(holder.getDeclaredMethods())); + executables.addAll(Arrays.asList(holder.getDeclaredConstructors())); + for (Executable executable : executables) { HotSpotResolvedJavaMethod method = CompilerToVMHelper - .getResolvedJavaMethodAtSlot(holder, i); - Asserts.assertNotNull(method, caseName + " did not got method"); - Asserts.assertEQ(holder, - CompilerToVMHelper.getMirror(method.getDeclaringClass()), - caseName + " : unexpected declaring class"); + .asResolvedJavaMethod(executable); + Asserts.assertNotNull(method, "could not convert " + method); } } } diff --git a/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java index 32959f2dd86..25cbb97b1b9 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java @@ -74,45 +74,37 @@ public class FindUniqueConcreteMethodTest { private static Set createTestCases() { Set result = new HashSet<>(); // a public method - result.add(new TestCase(true, SingleSubclass.class, - SingleSubclass.class, "usualMethod")); + result.add(new TestCase(true, SingleSubclass.class, "usualMethod")); // overriden method - result.add(new TestCase(true, SingleSubclass.class, - SingleSubclass.class, "overridenMethod")); + result.add(new TestCase(true, SingleSubclass.class, "overridenMethod")); // private method - result.add(new TestCase(true, SingleSubclass.class, - SingleSubclass.class, "privateMethod")); + result.add(new TestCase(true, SingleSubclass.class, "privateMethod")); // protected method - result.add(new TestCase(true, SingleSubclass.class, - SingleSubclass.class, "protectedMethod")); + result.add(new TestCase(true, SingleSubclass.class, "protectedMethod")); // default(package-private) method - result.add(new TestCase(true, SingleSubclass.class, - SingleSubclass.class, "defaultAccessMethod")); + result.add(new TestCase(true, SingleSubclass.class, "defaultAccessMethod")); // default interface method redefined in implementer - result.add(new TestCase(true, MultipleImplementer1.class, - MultipleImplementer1.class, "defaultMethod")); + result.add(new TestCase(true, MultipleImplementer1.class, "defaultMethod")); // interface method - result.add(new TestCase(true, MultipleImplementer1.class, - MultipleImplementer1.class, "testMethod")); + result.add(new TestCase(true, MultipleImplementer1.class, "testMethod")); // default interface method not redefined in implementer - result.add(new TestCase(true, SingleImplementer.class, - SingleImplementerInterface.class, "defaultMethod")); + // result.add(new TestCase(true, SingleImplementer.class, + // SingleImplementerInterface.class, "defaultMethod")); // static method - result.add(new TestCase(false, SingleSubclass.class, - SingleSubclass.class, "staticMethod")); + result.add(new TestCase(false, SingleSubclass.class, "staticMethod")); // interface method result.add(new TestCase(false, MultipleSuperImplementers.class, - DuplicateSimpleSingleImplementerInterface.class, "interfaceMethod", false)); + DuplicateSimpleSingleImplementerInterface.class, "interfaceMethod")); result.add(new TestCase(false, MultipleSuperImplementers.class, - SimpleSingleImplementerInterface.class, "interfaceMethod", false)); + SimpleSingleImplementerInterface.class, "interfaceMethod")); return result; } private void runTest(TestCase tcase) throws NoSuchMethodException { System.out.println(tcase); Method method = tcase.holder.getDeclaredMethod(tcase.methodName); - HotSpotResolvedJavaMethod testMethod = CTVMUtilities - .getResolvedMethod(tcase.methodFromReceiver ? tcase.receiver : tcase.holder, method); + HotSpotResolvedJavaMethod testMethod = CTVMUtilities.getResolvedMethod(method); + HotSpotResolvedObjectType resolvedType = CompilerToVMHelper .lookupType(Utils.toJVMTypeSignature(tcase.receiver), getClass(), /* resolve = */ true); @@ -127,25 +119,23 @@ public class FindUniqueConcreteMethodTest { public final Class holder; public final String methodName; public final boolean isPositive; - public final boolean methodFromReceiver; public TestCase(boolean isPositive, Class clazz, Class holder, - String methodName, boolean methodFromReceiver) { + String methodName) { this.receiver = clazz; this.methodName = methodName; this.isPositive = isPositive; this.holder = holder; - this.methodFromReceiver = methodFromReceiver; } - public TestCase(boolean isPositive, Class clazz, Class holder, String methodName) { - this(isPositive, clazz, holder, methodName, true); + public TestCase(boolean isPositive, Class clazz, String methodName) { + this(isPositive, clazz, clazz, methodName); } @Override public String toString() { - return String.format("CASE: receiver=%s, holder=%s, method=%s, isPositive=%s, methodFromReceiver=%s", - receiver.getName(), holder.getName(), methodName, isPositive, methodFromReceiver); + return String.format("CASE: receiver=%s, holder=%s, method=%s, isPositive=%s", + receiver.getName(), holder.getName(), methodName, isPositive); } } } diff --git a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java index 48fa29157b8..24a60d4992e 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java @@ -51,6 +51,7 @@ import jdk.vm.ci.hotspot.PublicMetaspaceWrapperObject; import sun.hotspot.WhiteBox; import java.lang.reflect.Field; +import java.lang.reflect.Method; public class GetResolvedJavaMethodTest { private static enum TestCase { @@ -64,9 +65,7 @@ public class GetResolvedJavaMethodTest { JAVA_METHOD_BASE { @Override HotSpotResolvedJavaMethod getResolvedJavaMethod() { - HotSpotResolvedJavaMethod methodInstance - = CompilerToVMHelper.getResolvedJavaMethodAtSlot( - TEST_CLASS, 0); + HotSpotResolvedJavaMethod methodInstance = TEST_METHOD; try { METASPACE_METHOD_FIELD.set(methodInstance, getPtrToMethod()); @@ -81,9 +80,7 @@ public class GetResolvedJavaMethodTest { @Override HotSpotResolvedJavaMethod getResolvedJavaMethod() { long ptr = getPtrToMethod(); - HotSpotResolvedJavaMethod methodInstance - = CompilerToVMHelper.getResolvedJavaMethodAtSlot( - TEST_CLASS, 0); + HotSpotResolvedJavaMethod methodInstance = TEST_METHOD; try { METASPACE_METHOD_FIELD.set(methodInstance, ptr / 2L); } catch (ReflectiveOperationException e) { @@ -97,9 +94,7 @@ public class GetResolvedJavaMethodTest { @Override HotSpotResolvedJavaMethod getResolvedJavaMethod() { long ptr = getPtrToMethod(); - HotSpotResolvedJavaMethod methodInstance - = CompilerToVMHelper.getResolvedJavaMethodAtSlot( - TEST_CLASS, 0); + HotSpotResolvedJavaMethod methodInstance = TEST_METHOD; try { METASPACE_METHOD_FIELD.set(methodInstance, 0L); } catch (ReflectiveOperationException e) { @@ -117,16 +112,21 @@ public class GetResolvedJavaMethodTest { private static final WhiteBox WB = WhiteBox.getWhiteBox(); private static final Field METASPACE_METHOD_FIELD; private static final Class TEST_CLASS = GetResolvedJavaMethodTest.class; + private static final HotSpotResolvedJavaMethod TEST_METHOD; private static final long PTR; static { - HotSpotResolvedJavaMethod method - = CompilerToVMHelper.getResolvedJavaMethodAtSlot(TEST_CLASS, 0); + try { + Method method = TEST_CLASS.getDeclaredMethod("test", TestCase.class); + TEST_METHOD = CompilerToVMHelper.asResolvedJavaMethod(method); + } catch (NoSuchMethodException e) { + throw new Error("TESTBUG : " + e, e); + } try { // jdk.vm.ci.hotspot.HotSpotResolvedJavaMethodImpl.metaspaceMethod - METASPACE_METHOD_FIELD = method.getClass() + METASPACE_METHOD_FIELD = TEST_METHOD.getClass() .getDeclaredField("metaspaceMethod"); METASPACE_METHOD_FIELD.setAccessible(true); - PTR = (long) METASPACE_METHOD_FIELD.get(method); + PTR = (long) METASPACE_METHOD_FIELD.get(TEST_METHOD); } catch (ReflectiveOperationException e) { throw new Error("TESTBUG : " + e, e); } diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MemoryAccessProviderData.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MemoryAccessProviderData.java index 549cc7b76ae..fcbc721caa8 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MemoryAccessProviderData.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MemoryAccessProviderData.java @@ -23,6 +23,10 @@ package jdk.vm.ci.hotspot.test; +import java.lang.reflect.Field; + +import org.testng.annotations.DataProvider; + import jdk.internal.misc.Unsafe; import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; @@ -32,27 +36,14 @@ import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.runtime.JVMCI; -import org.testng.annotations.DataProvider; - -import java.lang.reflect.Field; public class MemoryAccessProviderData { - private static final Unsafe UNSAFE = getUnsafe(); + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); private static final HotSpotConstantReflectionProvider CONSTANT_REFLECTION = (HotSpotConstantReflectionProvider) JVMCI.getRuntime().getHostJVMCIBackend().getConstantReflection(); private static final TestClass TEST_OBJECT = new TestClass(); private static final JavaConstant TEST_CONSTANT = CONSTANT_REFLECTION.forObject(TEST_OBJECT); private static final JavaConstant TEST_CLASS_CONSTANT = CONSTANT_REFLECTION.forObject(TestClass.class); - private static Unsafe getUnsafe() { - try { - Field f = Unsafe.class.getDeclaredField("theUnsafe"); - f.setAccessible(true); - return (Unsafe) f.get(null); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException("Unable to get Unsafe instance.", e); - } - } - @DataProvider(name = "positiveObject") public static Object[][] getPositiveObjectJavaKind() { HotSpotJVMCIRuntimeProvider runtime = (HotSpotJVMCIRuntimeProvider) JVMCI.getRuntime(); diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java index 2faefc8bc49..c1474c16c25 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java @@ -438,7 +438,6 @@ public class TestResolvedJavaMethod extends MethodUniverse { // @formatter:off private static final String[] untestedApiMethods = { - "invoke", "newInstance", "getDeclaringClass", "getEncoding", diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java index 86e54c9b7bc..be0b05563e1 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java @@ -35,28 +35,6 @@ package jdk.vm.ci.runtime.test; -import jdk.internal.reflect.ConstantPool; -import jdk.vm.ci.common.JVMCIError; -import jdk.vm.ci.meta.Assumptions.AssumptionResult; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ModifiersProvider; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; -import org.junit.Test; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - import static java.lang.reflect.Modifier.isAbstract; import static java.lang.reflect.Modifier.isFinal; import static java.lang.reflect.Modifier.isPrivate; @@ -70,6 +48,28 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.junit.Test; + +import jdk.internal.reflect.ConstantPool; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.Assumptions.AssumptionResult; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; + /** * Tests for {@link ResolvedJavaType}. */ @@ -146,8 +146,9 @@ public class TestResolvedJavaType extends TypeUniverse { public void getModifiersTest() { for (Class c : classes) { ResolvedJavaType type = metaAccess.lookupJavaType(c); - int expected = c.getModifiers() & ModifiersProvider.jvmClassModifiers(); - int actual = type.getModifiers() & ModifiersProvider.jvmClassModifiers(); + int mask = Modifier.classModifiers() & ~Modifier.STATIC; + int expected = c.getModifiers() & mask; + int actual = type.getModifiers() & mask; Class elementalType = c; while (elementalType.isArray()) { elementalType = elementalType.getComponentType(); diff --git a/hotspot/test/compiler/rtm/cli/RTMLockingAwareTest.java b/hotspot/test/compiler/rtm/cli/RTMLockingAwareTest.java index 6fcc2799aa9..f435c7dbb49 100644 --- a/hotspot/test/compiler/rtm/cli/RTMLockingAwareTest.java +++ b/hotspot/test/compiler/rtm/cli/RTMLockingAwareTest.java @@ -25,6 +25,7 @@ package compiler.rtm.cli; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.process.ExitCode; import jdk.test.lib.cli.CommandLineOptionTest; @@ -66,7 +67,7 @@ public abstract class RTMLockingAwareTest boolean isExperimental, String defaultValue, String[] correctValues, String[] incorrectValues, String warningMessage) { - super(new AndPredicate(new SupportedCPU(), new SupportedVM()), + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM()), optionName, isBoolean, isExperimental, defaultValue); this.correctValues = correctValues; this.incorrectValues = incorrectValues; diff --git a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java index 02f8acdc356..21773e4737f 100644 --- a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java @@ -42,6 +42,7 @@ package compiler.rtm.cli; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.cli.CommandLineOptionTest; import jdk.test.lib.cli.predicate.AndPredicate; @@ -49,7 +50,7 @@ import jdk.test.lib.cli.predicate.AndPredicate; public class TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig extends TestPrintPreciseRTMLockingStatisticsBase { private TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig() { - super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java index 3efcbf54eaa..27cea60ae3d 100644 --- a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java @@ -42,6 +42,7 @@ package compiler.rtm.cli; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.cli.predicate.AndPredicate; import jdk.test.lib.cli.predicate.NotPredicate; @@ -49,8 +50,8 @@ import jdk.test.lib.cli.predicate.NotPredicate; public class TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig extends TestPrintPreciseRTMLockingStatisticsBase { private TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig() { - super(new NotPredicate(new AndPredicate(new SupportedCPU(), - new SupportedVM()))); + super(new NotPredicate( + new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM()))); } public static void main(String args[]) throws Throwable { diff --git a/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java index 1fec34e405f..f3a7a94e912 100644 --- a/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java @@ -42,6 +42,7 @@ package compiler.rtm.cli; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.cli.predicate.AndPredicate; import jdk.test.lib.cli.predicate.NotPredicate; @@ -51,8 +52,8 @@ public class TestRTMAbortRatioOptionOnUnsupportedConfig private static final String DEFAULT_VALUE = "50"; private TestRTMAbortRatioOptionOnUnsupportedConfig() { - super(new NotPredicate(new AndPredicate(new SupportedVM(), - new SupportedCPU())), + super(new NotPredicate( + new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())), "RTMAbortRatio", false, true, TestRTMAbortRatioOptionOnUnsupportedConfig.DEFAULT_VALUE, "0", "10", "100", "200"); diff --git a/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java index fcbbfe7882e..2a26f2531cd 100644 --- a/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java @@ -42,6 +42,7 @@ package compiler.rtm.cli; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.cli.predicate.AndPredicate; import jdk.test.lib.cli.predicate.NotPredicate; @@ -51,8 +52,8 @@ public class TestRTMTotalCountIncrRateOptionOnUnsupportedConfig private static final String DEFAULT_VALUE = "64"; private TestRTMTotalCountIncrRateOptionOnUnsupportedConfig() { - super(new NotPredicate(new AndPredicate(new SupportedCPU(), - new SupportedVM())), + super(new NotPredicate( + new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())), "RTMTotalCountIncrRate", false, true, TestRTMTotalCountIncrRateOptionOnUnsupportedConfig .DEFAULT_VALUE, diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java index e674b46ebd6..80268cdb25e 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java @@ -42,6 +42,7 @@ package compiler.rtm.cli; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.process.ExitCode; import jdk.test.lib.cli.CommandLineOptionTest; @@ -52,7 +53,7 @@ public class TestUseRTMDeoptOptionOnSupportedConfig private static final String DEFAULT_VALUE = "false"; private TestUseRTMDeoptOptionOnSupportedConfig() { - super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java index e6397317e8f..91d55ffee90 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java @@ -42,6 +42,7 @@ package compiler.rtm.cli; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.cli.CommandLineOptionTest; import jdk.test.lib.cli.predicate.AndPredicate; @@ -52,8 +53,8 @@ public class TestUseRTMDeoptOptionOnUnsupportedConfig private static final String DEFAULT_VALUE = "false"; private TestUseRTMDeoptOptionOnUnsupportedConfig() { - super(new NotPredicate(new AndPredicate(new SupportedCPU(), - new SupportedVM())), + super(new NotPredicate( + new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())), "UseRTMDeopt", true, false, TestUseRTMDeoptOptionOnUnsupportedConfig.DEFAULT_VALUE, "true"); diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java index 9e2163bb26f..eae736f70aa 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java @@ -42,6 +42,7 @@ package compiler.rtm.cli; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.process.ExitCode; import jdk.test.lib.cli.CommandLineOptionTest; @@ -52,7 +53,7 @@ public class TestUseRTMForStackLocksOptionOnSupportedConfig private static final String DEFAULT_VALUE = "false"; private TestUseRTMForStackLocksOptionOnSupportedConfig() { - super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java index 84251d57807..2bf21de4fb5 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java @@ -42,6 +42,7 @@ package compiler.rtm.cli; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.process.ExitCode; import jdk.test.lib.cli.CommandLineOptionTest; @@ -53,8 +54,8 @@ public class TestUseRTMForStackLocksOptionOnUnsupportedConfig private static final String DEFAULT_VALUE = "false"; private TestUseRTMForStackLocksOptionOnUnsupportedConfig() { - super(new NotPredicate(new AndPredicate(new SupportedCPU(), - new SupportedVM())), + super(new NotPredicate( + new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())), "UseRTMForStackLocks", true, true, TestUseRTMForStackLocksOptionOnUnsupportedConfig.DEFAULT_VALUE, "true"); diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java index b0694e7508d..dac760c2e05 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java @@ -42,6 +42,7 @@ package compiler.rtm.cli; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.process.ExitCode; import jdk.test.lib.cli.CommandLineOptionTest; @@ -52,7 +53,7 @@ public class TestUseRTMLockingOptionOnSupportedConfig private static final String DEFAULT_VALUE = "false"; private TestUseRTMLockingOptionOnSupportedConfig() { - super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java index 3aeab02004d..992f58210b9 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java @@ -42,6 +42,7 @@ package compiler.rtm.cli; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.process.ExitCode; import jdk.test.lib.cli.CommandLineOptionTest; @@ -50,7 +51,7 @@ import jdk.test.lib.cli.predicate.AndPredicate; public class TestUseRTMLockingOptionWithBiasedLocking extends CommandLineOptionTest { private TestUseRTMLockingOptionWithBiasedLocking() { - super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java b/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java index b7ce4c62f07..c99a20274a3 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java @@ -45,6 +45,7 @@ import compiler.testlibrary.rtm.CompilableTest; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.internal.misc.Unsafe; import jdk.test.lib.Asserts; @@ -60,7 +61,7 @@ import java.util.List; */ public class TestRTMAbortRatio extends CommandLineOptionTest { private TestRTMAbortRatio() { - super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java b/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java index 6090fa19592..0f3c855c3fc 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java @@ -45,6 +45,7 @@ import compiler.testlibrary.rtm.AbortType; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; @@ -59,7 +60,7 @@ import java.util.List; */ public class TestRTMAbortThreshold extends CommandLineOptionTest { private TestRTMAbortThreshold() { - super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java b/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java index 48aea40ee8a..1c8d3d53727 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java @@ -47,6 +47,7 @@ import compiler.testlibrary.rtm.CompilableTest; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.internal.misc.Unsafe; import jdk.test.lib.Asserts; @@ -86,7 +87,7 @@ public class TestRTMAfterNonRTMDeopt extends CommandLineOptionTest { private static final String RANGE_CHECK = "range_check"; private TestRTMAfterNonRTMDeopt() { - super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java index 0633d8ab016..a8dd7c86d0e 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java @@ -45,6 +45,7 @@ import compiler.testlibrary.rtm.AbortType; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; @@ -66,7 +67,7 @@ public class TestRTMDeoptOnHighAbortRatio extends CommandLineOptionTest { = AbortProvoker.DEFAULT_ITERATIONS / 2L; private TestRTMDeoptOnHighAbortRatio() { - super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java index d936790c07d..6330ed272de 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java @@ -44,6 +44,7 @@ import compiler.testlibrary.rtm.CompilableTest; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.internal.misc.Unsafe; import jdk.test.lib.Asserts; @@ -66,7 +67,7 @@ public class TestRTMDeoptOnLowAbortRatio extends CommandLineOptionTest { private static final long ABORT_THRESHOLD = LOCKING_THRESHOLD / 2L; private TestRTMDeoptOnLowAbortRatio() { - super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java b/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java index 33e263cb940..06a7ec66f85 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java @@ -44,6 +44,7 @@ import compiler.testlibrary.rtm.AbortProvoker; import compiler.testlibrary.rtm.AbortType; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; @@ -58,7 +59,7 @@ public class TestRTMLockingCalculationDelay extends CommandLineOptionTest { private static final boolean INFLATE_MONITOR = true; private TestRTMLockingCalculationDelay() { - super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java b/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java index d42cde137f4..d8bbda017ec 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java @@ -45,6 +45,7 @@ import compiler.testlibrary.rtm.CompilableTest; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.internal.misc.Unsafe; import jdk.test.lib.Asserts; @@ -60,7 +61,7 @@ import java.util.List; */ public class TestRTMLockingThreshold extends CommandLineOptionTest { private TestRTMLockingThreshold() { - super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } /** diff --git a/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java b/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java index 5526e096c91..4c9ae84275b 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java @@ -44,6 +44,7 @@ import compiler.testlibrary.rtm.CompilableTest; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; @@ -64,7 +65,7 @@ public class TestRTMRetryCount extends CommandLineOptionTest { private static final boolean INFLATE_MONITOR = true; private TestRTMRetryCount() { - super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java b/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java index 61dc2bcccb7..73753b2ac82 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java @@ -45,6 +45,7 @@ import compiler.testlibrary.rtm.CompilableTest; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; @@ -66,7 +67,7 @@ public class TestRTMSpinLoopCount extends CommandLineOptionTest { = new int[] { 0, 100, 1_000, 1_000_000, 10_000_000 }; private TestRTMSpinLoopCount() { - super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java index 4e1e0d82fac..df98916596d 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java @@ -45,6 +45,7 @@ import compiler.testlibrary.rtm.CompilableTest; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.internal.misc.Unsafe; import jdk.test.lib.Asserts; @@ -64,7 +65,7 @@ import java.util.List; */ public class TestRTMTotalCountIncrRate extends CommandLineOptionTest { private TestRTMTotalCountIncrRate() { - super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java b/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java index f7a752f87fa..911793fefd3 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java @@ -45,6 +45,7 @@ import compiler.testlibrary.rtm.AbortType; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; @@ -73,7 +74,7 @@ public class TestUseRTMAfterLockInflation extends CommandLineOptionTest { = 2L * AbortProvoker.DEFAULT_ITERATIONS; private TestUseRTMAfterLockInflation() { - super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java b/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java index d9cf61552e4..4e6bfbf7bef 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java @@ -44,6 +44,7 @@ import compiler.testlibrary.rtm.AbortProvoker; import compiler.testlibrary.rtm.AbortType; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; @@ -56,7 +57,7 @@ import jdk.test.lib.cli.predicate.AndPredicate; */ public class TestUseRTMDeopt extends CommandLineOptionTest { private TestUseRTMDeopt() { - super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java b/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java index 038496e310a..43fdeee0832 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java @@ -43,6 +43,7 @@ import compiler.testlibrary.rtm.AbortType; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; @@ -63,7 +64,7 @@ import java.util.List; */ public class TestUseRTMForInflatedLocks extends CommandLineOptionTest { private TestUseRTMForInflatedLocks() { - super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java b/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java index cdb854a8dcc..50fd873af60 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java @@ -44,6 +44,7 @@ import compiler.testlibrary.rtm.AbortType; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; @@ -66,7 +67,7 @@ public class TestUseRTMForStackLocks extends CommandLineOptionTest { private static final boolean INFLATE_MONITOR = false; private TestUseRTMForStackLocks() { - super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java b/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java index 936e7c970b3..12c52263800 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java @@ -46,6 +46,7 @@ import compiler.testlibrary.rtm.CompilableTest; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; @@ -62,7 +63,7 @@ public class TestUseRTMXendForLockBusy extends CommandLineOptionTest { private final static int LOCKING_TIME = 5000; private TestUseRTMXendForLockBusy() { - super(new AndPredicate(new SupportedVM(), new SupportedCPU())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java b/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java index d92cb70bff8..bb4e6cad5b1 100644 --- a/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java +++ b/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java @@ -45,6 +45,7 @@ import compiler.testlibrary.rtm.AbortType; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; @@ -62,7 +63,7 @@ import java.util.List; */ public class TestNoRTMLockElidingOption extends CommandLineOptionTest { private TestNoRTMLockElidingOption() { - super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java b/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java index b649715510f..31ef8ab09ab 100644 --- a/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java +++ b/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java @@ -46,6 +46,7 @@ import compiler.testlibrary.rtm.AbortType; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; @@ -68,7 +69,7 @@ import java.util.List; */ public class TestUseRTMLockElidingOption extends CommandLineOptionTest { private TestUseRTMLockElidingOption() { - super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java b/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java index e9ec090799b..29ec33fd7b2 100644 --- a/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java +++ b/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java @@ -48,6 +48,7 @@ import compiler.testlibrary.rtm.AbortType; import compiler.testlibrary.rtm.RTMLockingStatistics; import compiler.testlibrary.rtm.RTMTestBase; import compiler.testlibrary.rtm.predicate.SupportedCPU; +import compiler.testlibrary.rtm.predicate.SupportedOS; import compiler.testlibrary.rtm.predicate.SupportedVM; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; @@ -67,7 +68,7 @@ import java.util.List; public class TestPrintPreciseRTMLockingStatistics extends CommandLineOptionTest { private TestPrintPreciseRTMLockingStatistics() { - super(new AndPredicate(new SupportedCPU(), new SupportedVM())); + super(new AndPredicate(new SupportedCPU(), new SupportedOS(), new SupportedVM())); } @Override diff --git a/hotspot/test/compiler/stringopts/TestStringObjectInitialization.java b/hotspot/test/compiler/stringopts/TestStringObjectInitialization.java index b25c225d413..c371a57ad7a 100644 --- a/hotspot/test/compiler/stringopts/TestStringObjectInitialization.java +++ b/hotspot/test/compiler/stringopts/TestStringObjectInitialization.java @@ -67,6 +67,11 @@ public class TestStringObjectInitialization { add(s + Arrays.toString(sArray) + " const "); } + public void reset() { + // Reset string to avoid OOMEs + myString = ""; + } + private static class Runner implements Runnable { private TestStringObjectInitialization test; @@ -76,8 +81,9 @@ public class TestStringObjectInitialization { public void run() { String[] array = {"a", "b", "c"}; - for (int i = 0; i < 10000; ++i) { + for (int i = 0; i < 100_000; ++i) { test.run("a", array); + test.reset(); } } } diff --git a/hotspot/test/compiler/testlibrary/rtm/RTMTestBase.java b/hotspot/test/compiler/testlibrary/rtm/RTMTestBase.java index 5fde3f21753..643f3bebcad 100644 --- a/hotspot/test/compiler/testlibrary/rtm/RTMTestBase.java +++ b/hotspot/test/compiler/testlibrary/rtm/RTMTestBase.java @@ -241,7 +241,8 @@ public class RTMTestBase { "-XX:-TieredCompilation", "-XX:+UseRTMLocking", CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI"); + "-Xbootclasspath/a:.", "-XX:+WhiteBoxAPI", + "-XaddExports:java.base/jdk.internal.misc=ALL-UNNAMED"); if (test != null) { for (String method : test.getMethodsToCompileNames()) { diff --git a/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedOS.java b/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedOS.java new file mode 100644 index 00000000000..6eee0046853 --- /dev/null +++ b/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedOS.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package compiler.testlibrary.rtm.predicate; + +import jdk.test.lib.Platform; + +import java.util.function.BooleanSupplier; + +public class SupportedOS implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + if (Platform.isAix()) { + // Actually, this works since AIX 7.1.3.30, but os.version property + // is set to 7.1. + return (Platform.getOsVersionMajor() > 7) || + (Platform.getOsVersionMajor() == 7 && Platform.getOsVersionMinor() > 1); + + } else if (Platform.isLinux()) { + if (Platform.isPPC()) { + return (Platform.getOsVersionMajor() > 4) || + (Platform.getOsVersionMajor() == 4 && Platform.getOsVersionMinor() > 1); + } + } + return true; + } +} diff --git a/hotspot/test/native/classfile/test_symbolTable.cpp b/hotspot/test/native/classfile/test_symbolTable.cpp new file mode 100644 index 00000000000..04e382c448e --- /dev/null +++ b/hotspot/test/native/classfile/test_symbolTable.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "runtime/interfaceSupport.hpp" +#include "classfile/symbolTable.hpp" +#include "unittest.hpp" + +TEST(SymbolTable, temp_new_symbol) { + // Assert messages assume these symbols are unique, and the refcounts start at + // one, but code does not rely on this. + JavaThread* THREAD = JavaThread::current(); + // the thread should be in vm to use locks + ThreadInVMfromNative ThreadInVMfromNative(THREAD); + + Symbol* abc = SymbolTable::new_symbol("abc", CATCH); + int abccount = abc->refcount(); + TempNewSymbol ss = abc; + ASSERT_EQ(ss->refcount(), abccount) << "only one abc"; + ASSERT_EQ(ss->refcount(), abc->refcount()) << "should match TempNewSymbol"; + + Symbol* efg = SymbolTable::new_symbol("efg", CATCH); + Symbol* hij = SymbolTable::new_symbol("hij", CATCH); + int efgcount = efg->refcount(); + int hijcount = hij->refcount(); + + TempNewSymbol s1 = efg; + TempNewSymbol s2 = hij; + ASSERT_EQ(s1->refcount(), efgcount) << "one efg"; + ASSERT_EQ(s2->refcount(), hijcount) << "one hij"; + + // Assignment operator + s1 = s2; + ASSERT_EQ(hij->refcount(), hijcount + 1) << "should be two hij"; + ASSERT_EQ(efg->refcount(), efgcount - 1) << "should be no efg"; + + s1 = ss; // s1 is abc + ASSERT_EQ(s1->refcount(), abccount + 1) << "should be two abc (s1 and ss)"; + ASSERT_EQ(hij->refcount(), hijcount) << "should only have one hij now (s2)"; + + s1 = s1; // self assignment + ASSERT_EQ(s1->refcount(), abccount + 1) << "should still be two abc (s1 and ss)"; + + TempNewSymbol s3; + Symbol* klm = SymbolTable::new_symbol("klm", CATCH); + int klmcount = klm->refcount(); + s3 = klm; // assignment + ASSERT_EQ(s3->refcount(), klmcount) << "only one klm now"; + + Symbol* xyz = SymbolTable::new_symbol("xyz", CATCH); + int xyzcount = xyz->refcount(); + { // inner scope + TempNewSymbol s_inner = xyz; + } + ASSERT_EQ(xyz->refcount(), xyzcount - 1) + << "Should have been decremented by dtor in inner scope"; +} diff --git a/hotspot/test/native/gc/g1/test_g1IHOPControl.cpp b/hotspot/test/native/gc/g1/test_g1IHOPControl.cpp new file mode 100644 index 00000000000..082b0886bf9 --- /dev/null +++ b/hotspot/test/native/gc/g1/test_g1IHOPControl.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "gc/g1/g1CollectedHeap.inline.hpp" +#include "gc/g1/g1IHOPControl.hpp" +#include "gc/g1/g1Predictions.hpp" +#include "unittest.hpp" + +static void test_update(G1IHOPControl* ctrl, double alloc_time, + size_t alloc_amount, size_t young_size, + double mark_time) { + for (int i = 0; i < 100; i++) { + ctrl->update_allocation_info(alloc_time, alloc_amount, young_size); + ctrl->update_marking_length(mark_time); + } +} + +// @requires UseG1GC +TEST_VM(G1StaticIHOPControl, simple) { + // Test requires G1 + if (!UseG1GC) { + return; + } + + const size_t initial_ihop = 45; + + G1StaticIHOPControl ctrl(initial_ihop); + ctrl.update_target_occupancy(100); + + size_t threshold = ctrl.get_conc_mark_start_threshold(); + EXPECT_EQ(initial_ihop, threshold); + + ctrl.update_allocation_info(100.0, 100, 100); + threshold = ctrl.get_conc_mark_start_threshold(); + EXPECT_EQ(initial_ihop, threshold); + + ctrl.update_marking_length(1000.0); + threshold = ctrl.get_conc_mark_start_threshold(); + EXPECT_EQ(initial_ihop, threshold); + + // Whatever we pass, the IHOP value must stay the same. + test_update(&ctrl, 2, 10, 10, 3); + threshold = ctrl.get_conc_mark_start_threshold(); + + EXPECT_EQ(initial_ihop, threshold); + + test_update(&ctrl, 12, 10, 10, 3); + threshold = ctrl.get_conc_mark_start_threshold(); + + EXPECT_EQ(initial_ihop, threshold); +} + +// @requires UseG1GC +TEST_VM(G1AdaptiveIHOPControl, simple) { + // Test requires G1 + if (!UseG1GC) { + return; + } + + const size_t initial_threshold = 45; + const size_t young_size = 10; + const size_t target_size = 100; + + // The final IHOP value is always + // target_size - (young_size + alloc_amount/alloc_time * marking_time) + + G1Predictions pred(0.95); + G1AdaptiveIHOPControl ctrl(initial_threshold, &pred, 0, 0); + ctrl.update_target_occupancy(target_size); + + // First "load". + const size_t alloc_time1 = 2; + const size_t alloc_amount1 = 10; + const size_t marking_time1 = 2; + const size_t settled_ihop1 = target_size + - (young_size + alloc_amount1 / alloc_time1 * marking_time1); + + size_t threshold; + threshold = ctrl.get_conc_mark_start_threshold(); + + EXPECT_EQ(initial_threshold, threshold); + + for (size_t i = 0; i < G1AdaptiveIHOPNumInitialSamples - 1; i++) { + ctrl.update_allocation_info(alloc_time1, alloc_amount1, young_size); + ctrl.update_marking_length(marking_time1); + // Not enough data yet. + threshold = ctrl.get_conc_mark_start_threshold(); + + ASSERT_EQ(initial_threshold, threshold) << "on step " << i; + } + + test_update(&ctrl, alloc_time1, alloc_amount1, young_size, marking_time1); + + threshold = ctrl.get_conc_mark_start_threshold(); + + EXPECT_EQ(settled_ihop1, threshold); + + // Second "load". A bit higher allocation rate. + const size_t alloc_time2 = 2; + const size_t alloc_amount2 = 30; + const size_t marking_time2 = 2; + const size_t settled_ihop2 = target_size + - (young_size + alloc_amount2 / alloc_time2 * marking_time2); + + test_update(&ctrl, alloc_time2, alloc_amount2, young_size, marking_time2); + + threshold = ctrl.get_conc_mark_start_threshold(); + + EXPECT_LT(threshold, settled_ihop1); + + // Third "load". Very high (impossible) allocation rate. + const size_t alloc_time3 = 1; + const size_t alloc_amount3 = 50; + const size_t marking_time3 = 2; + const size_t settled_ihop3 = 0; + + test_update(&ctrl, alloc_time3, alloc_amount3, young_size, marking_time3); + threshold = ctrl.get_conc_mark_start_threshold(); + + EXPECT_EQ(settled_ihop3, threshold); + + // And back to some arbitrary value. + test_update(&ctrl, alloc_time2, alloc_amount2, young_size, marking_time2); + + threshold = ctrl.get_conc_mark_start_threshold(); + + EXPECT_GT(threshold, settled_ihop3); +} diff --git a/hotspot/test/native/oops/test_arrayOop.cpp b/hotspot/test/native/oops/test_arrayOop.cpp new file mode 100644 index 00000000000..915ff34380f --- /dev/null +++ b/hotspot/test/native/oops/test_arrayOop.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "oops/arrayOop.hpp" +#include "oops/oop.inline.hpp" +#include "unittest.hpp" +#include "utilities/globalDefinitions.hpp" + +class arrayOopDescTest { + public: + + static int header_size_in_bytes() { + return arrayOopDesc::header_size_in_bytes(); + } +}; + +static bool check_max_length_overflow(BasicType type) { + julong length = arrayOopDesc::max_array_length(type); + julong bytes_per_element = type2aelembytes(type); + julong bytes = length * bytes_per_element + + arrayOopDescTest::header_size_in_bytes(); + return (julong) (size_t) bytes == bytes; +} + +TEST(arrayOopDesc, boolean) { + ASSERT_PRED1(check_max_length_overflow, T_BOOLEAN); +} + +TEST(arrayOopDesc, char) { + ASSERT_PRED1(check_max_length_overflow, T_CHAR); +} + +TEST(arrayOopDesc, float) { + ASSERT_PRED1(check_max_length_overflow, T_FLOAT); +} + +TEST(arrayOopDesc, double) { + ASSERT_PRED1(check_max_length_overflow, T_DOUBLE); +} + +TEST(arrayOopDesc, byte) { + ASSERT_PRED1(check_max_length_overflow, T_BYTE); +} + +TEST(arrayOopDesc, short) { + ASSERT_PRED1(check_max_length_overflow, T_SHORT); +} + +TEST(arrayOopDesc, int) { + ASSERT_PRED1(check_max_length_overflow, T_INT); +} + +TEST(arrayOopDesc, long) { + ASSERT_PRED1(check_max_length_overflow, T_LONG); +} + +TEST(arrayOopDesc, object) { + ASSERT_PRED1(check_max_length_overflow, T_OBJECT); +} + +TEST(arrayOopDesc, array) { + ASSERT_PRED1(check_max_length_overflow, T_ARRAY); +} + +TEST(arrayOopDesc, narrowOop) { + ASSERT_PRED1(check_max_length_overflow, T_NARROWOOP); +} +// T_VOID and T_ADDRESS are not supported by max_array_length() diff --git a/hotspot/test/native/runtime/test_instanceKlass.cpp b/hotspot/test/native/oops/test_instanceKlass.cpp similarity index 74% rename from hotspot/test/native/runtime/test_instanceKlass.cpp rename to hotspot/test/native/oops/test_instanceKlass.cpp index 493a4e5d58c..2e223bc3bed 100644 --- a/hotspot/test/native/runtime/test_instanceKlass.cpp +++ b/hotspot/test/native/oops/test_instanceKlass.cpp @@ -19,18 +19,29 @@ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. - * */ #include "precompiled.hpp" #include "classfile/symbolTable.hpp" +#include "classfile/systemDictionary.hpp" #include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" #include "unittest.hpp" // Tests InstanceKlass::package_from_name() -TEST_VM(instanceKlass, null_symbol) { +TEST_VM(InstanceKlass, null_symbol) { ResourceMark rm; TempNewSymbol package_sym = InstanceKlass::package_from_name(NULL, NULL); ASSERT_TRUE(package_sym == NULL) << "Wrong package for NULL symbol"; } + +// Tests for InstanceKlass::is_class_loader_instance_klass() function +TEST_VM(InstanceKlass, class_loader_class) { + InstanceKlass* klass = SystemDictionary::ClassLoader_klass(); + ASSERT_TRUE(klass->is_class_loader_instance_klass()); +} + +TEST_VM(InstanceKlass, string_klass) { + InstanceKlass* klass = SystemDictionary::String_klass(); + ASSERT_TRUE(!klass->is_class_loader_instance_klass()); +} diff --git a/hotspot/src/share/vm/utilities/chunkedList.cpp b/hotspot/test/native/utilities/test_chunkedList.cpp similarity index 57% rename from hotspot/src/share/vm/utilities/chunkedList.cpp rename to hotspot/test/native/utilities/test_chunkedList.cpp index caf80e7c102..73a54886606 100644 --- a/hotspot/src/share/vm/utilities/chunkedList.cpp +++ b/hotspot/test/native/utilities/test_chunkedList.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -19,42 +19,40 @@ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. - * */ #include "precompiled.hpp" +#include "unittest.hpp" #include "utilities/chunkedList.hpp" -#include "utilities/debug.hpp" -/////////////// Unit tests /////////////// - -#ifndef PRODUCT +class Metadata; template class TestChunkedList { typedef ChunkedList ChunkedListT; public: + static void testEmpty() { ChunkedListT buffer; - assert(buffer.size() == 0, "assert"); + ASSERT_EQ((size_t) 0, buffer.size()); } static void testFull() { ChunkedListT buffer; for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { - buffer.push((T)i); + buffer.push((T) i); } - assert(buffer.size() == ChunkedListT::BufferSize, "assert"); - assert(buffer.is_full(), "assert"); + ASSERT_EQ((size_t) ChunkedListT::BufferSize, buffer.size()); + ASSERT_TRUE(buffer.is_full()); } static void testSize() { ChunkedListT buffer; for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { - assert(buffer.size() == i, "assert"); - buffer.push((T)i); - assert(buffer.size() == i + 1, "assert"); + ASSERT_EQ((size_t) i, buffer.size()); + buffer.push((T) i); + ASSERT_EQ((size_t) (i + 1), buffer.size()); } } @@ -62,48 +60,71 @@ class TestChunkedList { ChunkedListT buffer; buffer.clear(); - assert(buffer.size() == 0, "assert"); + ASSERT_EQ((size_t) 0, buffer.size()); for (uintptr_t i = 0; i < ChunkedListT::BufferSize / 2; i++) { - buffer.push((T)i); + buffer.push((T) i); } buffer.clear(); - assert(buffer.size() == 0, "assert"); + ASSERT_EQ((size_t) 0, buffer.size()); for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { - buffer.push((T)i); + buffer.push((T) i); } buffer.clear(); - assert(buffer.size() == 0, "assert"); + ASSERT_EQ((size_t) 0, buffer.size()); } static void testAt() { ChunkedListT buffer; for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { - buffer.push((T)i); - assert(buffer.at(i) == (T)i, "assert"); + buffer.push((T) i); + ASSERT_EQ((T) i, buffer.at(i)); } for (uintptr_t i = 0; i < ChunkedListT::BufferSize; i++) { - assert(buffer.at(i) == (T)i, "assert"); + ASSERT_EQ((T) i, buffer.at(i)); } } - - static void test() { - testEmpty(); - testFull(); - testSize(); - testClear(); - testAt(); - } }; -class Metadata; - -void TestChunkedList_test() { - TestChunkedList::test(); - TestChunkedList::test(); +TEST(ChunkedList, metadata_empty) { + TestChunkedList::testEmpty(); } -#endif +TEST(ChunkedList, metadata_full) { + TestChunkedList::testFull(); +} + +TEST(ChunkedList, metadata_size) { + TestChunkedList::testSize(); +} + +TEST(ChunkedList, metadata_clear) { + TestChunkedList::testSize(); +} + +TEST(ChunkedList, metadata_at) { + TestChunkedList::testAt(); +} + +TEST(ChunkedList, size_t_empty) { + TestChunkedList::testEmpty(); +} + +TEST(ChunkedList, size_t_full) { + TestChunkedList::testFull(); +} + +TEST(ChunkedList, size_t_size) { + TestChunkedList::testSize(); +} + +TEST(ChunkedList, size_t_clear) { + TestChunkedList::testSize(); +} + +TEST(ChunkedList, size_t_at) { + TestChunkedList::testAt(); +} diff --git a/hotspot/test/native/utilities/test_json.cpp b/hotspot/test/native/utilities/test_json.cpp new file mode 100644 index 00000000000..6eb9c31696c --- /dev/null +++ b/hotspot/test/native/utilities/test_json.cpp @@ -0,0 +1,515 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "prims/jvm.h" +#include "utilities/json.hpp" +#include "unittest.hpp" + +class JSON_GTest : public JSON { +public: + static void test(const char* json, bool valid); + +private: + JSON_GTest(const char* text); + + void log(uint level, const char* format, ...) ATTRIBUTE_PRINTF(3, 4); + + bool callback(JSON_TYPE t, JSON_VAL* v, uint level); + JSON_TYPE prev; +}; + +void JSON_GTest::test(const char* text, bool should_pass) { + JSON_GTest json(text); + if (should_pass) { + ASSERT_TRUE(json.valid()) << "failed on a valid json string"; + } else { + ASSERT_FALSE(json.valid()) << "succeeded on an invalid json string"; + } +} + +JSON_GTest::JSON_GTest(const char* text) : JSON(text, false, tty) { + prev = JSON_NONE; + parse(); +} + +TEST(utilities, json_curly_braces) { + JSON_GTest::test("{}", true); +} + +TEST(utilities, json_brackets) { + JSON_GTest::test("[]", true); +} + +TEST(utilities, json_space_braces) { + JSON_GTest::test(" { } ", true); +} + +TEST(utilities, json_space_bracketes) { + JSON_GTest::test(" [ ] ", true); +} + +TEST(utilities, json_quoted_error) { + JSON_GTest::test("\"error\"", false); +} + +TEST(utilities, json_error_string) { + JSON_GTest::test("error", false); +} + +TEST(utilities, json_simple_integer) { + JSON_GTest::test("1", false); +} + +TEST(utilities, json_siple_float) { + JSON_GTest::test("1.2", false); +} + +TEST(utilities, json_simple_boolean_true) { + JSON_GTest::test("true", false); +} + +TEST(utilities, json_simple_boolean_false) { + JSON_GTest::test("false", false); +} + +TEST(utilities, json_simple_null) { + JSON_GTest::test("null", false); +} + +TEST(utilities, json_one_element_int_array) { + JSON_GTest::test("[ 1 ]", true); +} + +TEST(utilities, json_int_array) { + JSON_GTest::test("[ 1, ]", true); +} + +TEST(utilities, json_one_element_bool_array) { + JSON_GTest::test("[ true ]", true); +} + +TEST(utilities, json_bool_array) { + JSON_GTest::test("[ true, ]", true); +} + +TEST(utilities, json_one_element_false_array) { + JSON_GTest::test("[ false ]", true); +} + +TEST(utilities, json_false_bool_array) { + JSON_GTest::test("[ false, ]", true); +} + +TEST(utilities, json_one_null_array) { + JSON_GTest::test("[ null ]", true); +} + +TEST(utilities, json_null_array) { + JSON_GTest::test("[ null, ]", true); +} + +TEST(utilities, json_one_empty_string_array) { + JSON_GTest::test("[ \"\" ]", true); +} + +TEST(utilities, json_empty_string_array) { + JSON_GTest::test("[ \"\", ]", true); +} + +TEST(utilities, json_single_string_array) { + JSON_GTest::test("[ \"elem1\" ]", true); +} + +TEST(utilities, json_string_comma_arrray) { + JSON_GTest::test("[ \"elem1\", ]", true); +} + +TEST(utilities, json_two_strings_array) { + JSON_GTest::test("[ \"elem1\", \"elem2\" ]", true); +} + +TEST(utilities, json_two_strings_comma_array) { + JSON_GTest::test("[ \"elem1\", \"elem2\", ]", true); +} + +TEST(utilities, json_curly_braces_outside) { + JSON_GTest::test("[ \"elem1\" ] { }", false); +} + +TEST(utilities, json_element_in_array) { + JSON_GTest::test("[ elem1, \"elem2\" ]", false); +} + +TEST(utilities, json_incorrect_end_array) { + JSON_GTest::test("[ \"elem1\"", false); +} + +TEST(utilities, json_incorrect_string_end) { + JSON_GTest::test("[ \"elem1 ]", false); +} + +TEST(utilities, json_incorrect_end_of_two_elements_array) { + JSON_GTest::test("[ \"elem1\", \"elem2\"", false); +} + +TEST(utilities, json_incorrect_bool_true_array) { + JSON_GTest::test("[ truefoo ]", false); +} + +TEST(utilities, json_incorrect_bool_false_array) { + JSON_GTest::test("[ falsefoo ]", false); +} + +TEST(utilities, json_incorrect_null_array) { + JSON_GTest::test("[ nullfoo ]", false); +} + +TEST(utilities, json_key_pair) { + JSON_GTest::test("{ key : 1 }", true); +} + +TEST(utilities, json_key_pair_comma) { + JSON_GTest::test("{ key : 1, }", true); +} + +TEST(utilities, json_bool_true_key) { + JSON_GTest::test("{ key : true }", true); +} + +TEST(utilities, json_bool_true_key_comma) { + JSON_GTest::test("{ key : true, }", true); +} + +TEST(utilities, json_bool_false_key) { + JSON_GTest::test("{ key : false }", true); +} + +TEST(utilities, json_bool_false_key_comma) { + JSON_GTest::test("{ key : false, }", true); +} + +TEST(utilities, json_null_key) { + JSON_GTest::test("{ key : null }", true); +} + +TEST(utilities, json_null_key_comma) { + JSON_GTest::test("{ key : null, }", true); +} + +TEST(utilities, json_pair_of_empty_strings) { + JSON_GTest::test("{ \"\" : \"\" }", true); +} + +TEST(utilities, json_pair_of_empty_strings_comma) { + JSON_GTest::test("{ \"\" : \"\", }", true); +} + +TEST(utilities, json_pair_of_strings) { + JSON_GTest::test("{ \"key1\" : \"val1\" }", true); +} + +TEST(utilities, json_pair_of_strings_comma) { + JSON_GTest::test("{ \"key1\" : \"val1\", }", true); +} + +TEST(utilities, json_two_pairs_of_strings) { + JSON_GTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\" }", true); +} + +TEST(utilities, json_two_pairs_of_strings_comma) { + JSON_GTest::test("{ \"key1\" : \"val1\", \"key2\" : \"val2\", }", true); +} + +TEST(utilities, json_array_outside) { + JSON_GTest::test("{ \"key\" : \"val\" } [ \"error\" ]", false); +} + +TEST(utilities, json_incorrect_object_end) { + JSON_GTest::test("{ \"key\" : \"val\" ", false); +} + +TEST(utilities, json_empty_comment) { + JSON_GTest::test("/**/ { }", true); +} + +TEST(utilities, json_space_comment) { + JSON_GTest::test("/* */ { }", true); +} + +TEST(utilities, json_comment) { + JSON_GTest::test("/*foo*/ { }", true); +} + +TEST(utilities, json_star_comment) { + JSON_GTest::test("/* *foo */ { }", true); +} + +TEST(utilities, json_stars_comment) { + JSON_GTest::test("/* *foo* */ { }", true); +} + +TEST(utilities, json_special_comment) { + JSON_GTest::test("/* /*foo */ { }", true); +} + +TEST(utilities, json_comment_after) { + JSON_GTest::test("{ } /* foo */", true); +} + +TEST(utilities, json_comment_after_and_space) { + JSON_GTest::test("{ } /* foo */ ", true); +} + +TEST(utilities, json_one_line_empty_comment_after) { + JSON_GTest::test("{ } //", true); +} + +TEST(utilities, json_one_line_space_comment_after) { + JSON_GTest::test("{ } // ", true); +} + +TEST(utilities, json_one_line_comment_after) { + JSON_GTest::test("{ } // foo", true); +} + +TEST(utilities, json_incorrect_multiline_comment) { + JSON_GTest::test("/* * / { }", false); +} + +TEST(utilities, json_incorrect_multiline_comment_begin) { + JSON_GTest::test("/ * */ { }", false); +} + +TEST(utilities, json_oneline_comment_only) { + JSON_GTest::test("// { }", false); +} + +TEST(utilities, json_multiline_comment_only) { + JSON_GTest::test("/* { } */", false); +} + +TEST(utilities, json_multiline_comment_2) { + JSON_GTest::test("/* { } */ ", false); +} + +TEST(utilities, json_incorrectly_commented_object) { + JSON_GTest::test("/* { } ", false); +} + +TEST(utilities, json_missing_multiline_end) { + JSON_GTest::test("{ } /* ", false); +} + +TEST(utilities, json_missing_multiline_slash) { + JSON_GTest::test("/* { } *", false); +} + +TEST(utilities, json_commented_object_end) { + JSON_GTest::test("{ /* } */", false); +} + +TEST(utilities, json_commented_array_end) { + JSON_GTest::test("[ /* ] */", false); +} + +TEST(utilities, json_missing_object_end) { + JSON_GTest::test("{ key : \"val\", /* } */", false); +} + +TEST(utilities, json_missing_array_end) { + JSON_GTest::test("[ \"val\", /* ] */", false); +} + +TEST(utilities, json_key_values_1) { + JSON_GTest::test("/* comment */{ key1 : { \"key2\" : { \"key3\" : [ \"elem1\", \"elem2\"," + "{ \"key4\" : null }, 3 , 2 , 1 , 0 , -1 , -2 , -3 , true, false, null, ] }, \"key5\"" + " : true }, \"key6\" : [ \"☃\" ], key7 : \"val\",}", true); +} + +TEST(utilities, json_key_values_2) { + JSON_GTest::test("/* comment */ { \"key1\" : { \"key2\" : { \"key3\" : [ \"elem1\", \"elem2\"," + "{ \"key4\" : null }, 3 , 2 , 1 , 0 , -1 , -2 , -3 , true, false, null, ] }, \"key5\"" + " : true }, \"key6\" : [ \"☃\" ], key7 : \"val\",}", true); +} + +TEST(utilities, json_quoted_symbols) { + JSON_GTest::test("/*comment*/{\"ff1 fsd\":{\"☃\":{\"☃\":[\"☃\",\"☃\"]}," + "\"☃\":true},\"☃\":[\"☃\"],\"foo\":\"☃\",}", true); +} + +TEST(utilities, json_incorrect_key) { + JSON_GTest::test("/* comment */ { key1 error : { \"☃\" : { \"☃\" : [ \"☃\"," + " \"☃\" ] }, \"☃\" : true }, \"baz\" : [ \"☃\" ], foo : \"☃\",}", + false); // first key needs to be quoted since it contains a space +} + +TEST(utilities, json_array_with_newline) { + JSON_GTest::test("[\n]", true); +} + +TEST(utilities, json_directives_file) { + JSON_GTest::test( + "[" "\n" + " {" + " // pattern to match against class+method+signature" "\n" + " // leading and trailing wildcard (*) allowed" "\n" + " match: \"foo.bar.*\"," "\n" + " " "\n" + " // override defaults for specified compiler" "\n" + " // we may differentiate between levels too. TBD." "\n" + " c1: {" "\n" + " //override c1 presets " "\n" + " array_bounds_check_removal: false" "\n" + " }," "\n" + "" "\n" + " c2: {" "\n" + " // control inlining of method" "\n" + " // + force inline, - dont inline" "\n" + " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n" + " }," "\n" + "" "\n" + " // directives outside a specific preset applies to all compilers" "\n" + " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n" + " print_assembly: true," "\n" + " verify_oopmaps: true," "\n" + " max_loop_unrolling: 5" "\n" + " }," "\n" + " {" "\n" + " // matching several patterns require an array" "\n" + " match: [\"baz.*\",\"frob*\"]," "\n" + "" "\n" + " // only enable c1 for this directive" "\n" + " // all enabled by default. Command disables all not listed" "\n" + " enable: \"c1\"," "\n" + "" "\n" + " // applies to all compilers" "\n" + " // + force inline, - dont inline" "\n" + " inline : [ \"+java.util.*\", \"-com.sun.*\"]," "\n" + " print_inlining: true," "\n" + "" "\n" + " // force matching compiles to be blocking/syncronous" "\n" + " blocking_compile: true" "\n" + " }," "\n" + "]" "\n", true); +} + +void JSON_GTest::log(uint indent, const char* format, ...) { + if (prev != JSON_KEY) { + for (uint i = 0; i < indent; i++) { + _st->print(" "); + } + } + va_list args; + va_start(args, format); + _st->vprint(format, args); + va_end(args); +} + +bool JSON_GTest::callback(JSON_TYPE t, JSON_VAL* v, uint rlevel) { + switch (t) { + case JSON_OBJECT_BEGIN: + log(rlevel, "{\n"); + prev = JSON_NONE; // Only care about JSON_KEY, to indent correctly + return true; + + case JSON_OBJECT_END: + log(rlevel, "},\n"); + prev = JSON_NONE; + return true; + + case JSON_ARRAY_BEGIN: + log(rlevel, "[\n"); + prev = JSON_NONE; + return true; + + case JSON_ARRAY_END: + log(rlevel, "],\n"); + prev = JSON_NONE; + return true; + + case JSON_KEY: + for (uint i = 0; i < rlevel; i++) { + _st->print(" "); + } + _st->print(""); + for (size_t i = 0; i < v->str.length; i++) { + u_char c = v->str.start[i]; + if (c == 0) { + return false; + } + _st->print("%c", c); + } + _st->print(" : "); + prev = JSON_KEY; + return true; + + case JSON_STRING: + if (prev != JSON_KEY) { + for (uint i = 0; i < rlevel; i++) { + _st->print(" "); + } + } + _st->print(""); + for (size_t i = 0; i < v->str.length; i++) { + u_char c = v->str.start[i]; + if (c == 0) { + return false; + } + _st->print("%c", c); + } + _st->print(",\n"); + prev = JSON_NONE; + return true; + + case JSON_NUMBER_INT: + log(rlevel, "%" PRId64 ",\n", v->int_value); + prev = JSON_NONE; + return true; + + case JSON_NUMBER_FLOAT: + log(rlevel, "%lf,\n", v->double_value); + prev = JSON_NONE; + return true; + + case JSON_TRUE: + log(rlevel, ",\n"); + prev = JSON_NONE; + return true; + + case JSON_FALSE: + log(rlevel, ",\n"); + prev = JSON_NONE; + return true; + + case JSON_NULL: + log(rlevel, ",\n"); + prev = JSON_NONE; + return true; + + default: + error(INTERNAL_ERROR, "unknown JSON type"); + return false; + } +} diff --git a/hotspot/src/share/vm/utilities/linkedlist.cpp b/hotspot/test/native/utilities/test_linkedlist.cpp similarity index 53% rename from hotspot/src/share/vm/utilities/linkedlist.cpp rename to hotspot/test/native/utilities/test_linkedlist.cpp index ba96b2e247f..34aa774ebdc 100644 --- a/hotspot/src/share/vm/utilities/linkedlist.cpp +++ b/hotspot/test/native/utilities/test_linkedlist.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -19,96 +19,103 @@ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. - * + */ #include "precompiled.hpp" - -/////////////// Unit tests /////////////// - -#ifndef PRODUCT - -#include "runtime/os.hpp" +#include "unittest.hpp" #include "utilities/linkedlist.hpp" -#include "memory/allocation.hpp" -#include "memory/allocation.inline.hpp" class Integer : public StackObj { private: - int _value; + int _value; public: - Integer(int i) : _value(i) { } - int value() const { return _value; } - bool equals(const Integer& i) const { - return _value == i.value(); + Integer(int i) : _value(i) { + } + + int value() const { + return _value; + } + + bool equals(const Integer& i) const { + return _value == i.value(); + } + + static int compare(const Integer& i1, const Integer& i2) { + return i1.value() - i2.value(); } }; -int compare_Integer(const Integer& i1, const Integer& i2) { - return i1.value() - i2.value(); -} - -void check_list_values(const int* expected, const LinkedList* list) { +static void check_list_values(const int* expected, const LinkedList* list) { LinkedListNode* head = list->head(); int index = 0; while (head != NULL) { - assert(head->peek()->value() == expected[index], "Unexpected value"); + ASSERT_EQ(expected[index], head->peek()->value()) + << "Unexpected value at index " << index; head = head->next(); - index ++; + index++; } } -void Test_linked_list() { - LinkedListImpl ll; +const Integer one(1), two(2), three(3), four(4), five(5), six(6); +// Test regular linked list +TEST(LinkedList, simple) { + LinkedListImpl ll; - // Test regular linked list - assert(ll.is_empty(), "Start with empty list"); - Integer one(1), two(2), three(3), four(4), five(5), six(6); + ASSERT_TRUE(ll.is_empty()) << "Start with empty list"; ll.add(six); - assert(!ll.is_empty(), "Should not be empty"); + ASSERT_TRUE(!ll.is_empty()) << "Should not be empty"; Integer* i = ll.find(six); - assert(i != NULL, "Should find it"); + ASSERT_TRUE(i != NULL) << "Should find it"; + ASSERT_EQ(six.value(), i->value()) << "Should be 6"; i = ll.find(three); - assert(i == NULL, "Not in the list"); + ASSERT_EQ(NULL, i) << "Not in the list"; LinkedListNode* node = ll.find_node(six); - assert(node != NULL, "6 is in the list"); + ASSERT_TRUE(node != NULL) << "6 is in the list"; ll.insert_after(three, node); ll.insert_before(one, node); int expected[3] = {1, 6, 3}; check_list_values(expected, &ll); +} +// Test sorted linked list +TEST(SortedLinkedList, simple) { + LinkedListImpl ll; + ll.add(one); + ll.add(six); + ll.add(three); ll.add(two); ll.add(four); ll.add(five); - // Test sorted linked list - SortedLinkedList sl; - assert(sl.is_empty(), "Start with empty list"); + SortedLinkedList sl; + ASSERT_TRUE(sl.is_empty()) << "Start with empty list"; size_t ll_size = ll.size(); sl.move(&ll); size_t sl_size = sl.size(); - assert(ll_size == sl_size, "Should be the same size"); - assert(ll.is_empty(), "No more entires"); + ASSERT_EQ(ll_size, sl_size) << "Should be the same size"; + ASSERT_TRUE(ll.is_empty()) << "No more entries"; // sorted result int sorted_result[] = {1, 2, 3, 4, 5, 6}; check_list_values(sorted_result, &sl); + if (HasFatalFailure()) { + return; + } - node = sl.find_node(four); - assert(node != NULL, "4 is in the list"); + LinkedListNode* node = sl.find_node(four); + ASSERT_TRUE(node != NULL) << "4 is in the list"; sl.remove_before(node); sl.remove_after(node); int remains[] = {1, 2, 4, 6}; check_list_values(remains, &sl); } -#endif // PRODUCT - diff --git a/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java b/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java index 65cb422adad..14603a5f1c6 100644 --- a/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java +++ b/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTest.java @@ -34,14 +34,17 @@ * jdk.hotspot.agent/sun.jvm.hotspot.runtime * jdk.hotspot.agent/sun.jvm.hotspot.tools * java.management - * @build SASymbolTableTestAgent SASymbolTableTestAttachee + * @build SASymbolTableTestAgent * @run main SASymbolTableTest */ +import java.util.Arrays; +import java.util.List; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.JDKToolFinder; import jdk.test.lib.Platform; +import jdk.test.lib.apps.LingeredApp; /* * The purpose of this test is to validate that we can use SA to @@ -53,6 +56,7 @@ import jdk.test.lib.Platform; */ public class SASymbolTableTest { static String jsaName = "./SASymbolTableTest.jsa"; + private static LingeredApp theApp = null; public static void main(String[] args) throws Exception { if (!Platform.shouldSAAttach()) { @@ -78,50 +82,44 @@ public class SASymbolTableTest { private static void run(boolean useArchive) throws Exception { String flag = useArchive ? "auto" : "off"; - // (1) Launch the attachee process - ProcessBuilder attachee = ProcessTools.createJavaProcessBuilder( - "-XX:+UnlockDiagnosticVMOptions", - "-XX:SharedArchiveFile=" + jsaName, - "-Xshare:" + flag, - "-showversion", // so we can see "sharing" in the output - "SASymbolTableTestAttachee"); + try { + // (1) Launch the attachee process + System.out.println("Starting LingeredApp"); + List vmOpts = Arrays.asList( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedArchiveFile=" + jsaName, + "-Xshare:" + flag, + "-showversion"); // so we can see "sharing" in the output - final Process p = attachee.start(); + theApp = LingeredApp.startApp(vmOpts); - // (2) Launch the agent process - long pid = p.getPid(); - System.out.println("Attaching agent " + pid); - ProcessBuilder tool = ProcessTools.createJavaProcessBuilder( - "--add-modules=jdk.hotspot.agent", - "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED", - "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.memory=ALL-UNNAMED", - "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.runtime=ALL-UNNAMED", - "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.tools=ALL-UNNAMED", - "SASymbolTableTestAgent", - Long.toString(pid)); - OutputAnalyzer output = ProcessTools.executeProcess(tool); - System.out.println(output.getOutput()); - output.shouldHaveExitValue(0); - - Thread t = new Thread() { - public void run() { - try { - OutputAnalyzer output = new OutputAnalyzer(p); - System.out.println("STDOUT["); - System.out.print(output.getStdout()); - System.out.println("]"); - System.out.println("STDERR["); - System.out.print(output.getStderr()); - System.out.println("]"); - } catch (Throwable t) { - t.printStackTrace(); - } - } - }; - t.start(); - - Thread.sleep(2 * 1000); - p.destroy(); - t.join(); + // (2) Launch the agent process + long pid = theApp.getPid(); + System.out.println("Attaching agent to " + pid ); + ProcessBuilder tool = ProcessTools.createJavaProcessBuilder( + "--add-modules=jdk.hotspot.agent", + "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED", + "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.memory=ALL-UNNAMED", + "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.runtime=ALL-UNNAMED", + "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.tools=ALL-UNNAMED", + "SASymbolTableTestAgent", + Long.toString(pid)); + OutputAnalyzer output = ProcessTools.executeProcess(tool); + System.out.println("STDOUT["); + System.out.println(output.getOutput()); + if (output.getStdout().contains("connected too early")) { + System.out.println("SymbolTable not created by VM - test skipped"); + return; + } + System.out.println("]"); + System.out.println("STDERR["); + System.out.print(output.getStderr()); + System.out.println("]"); + output.shouldHaveExitValue(0); + } catch (Exception ex) { + throw new RuntimeException("Test ERROR " + ex, ex); + } finally { + LingeredApp.stopApp(theApp); + } } } diff --git a/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTestAgent.java b/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTestAgent.java index 4c5193fbcc4..6be0e86976f 100644 --- a/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTestAgent.java +++ b/hotspot/test/runtime/SharedArchiveFile/SASymbolTableTestAgent.java @@ -112,31 +112,35 @@ public class SASymbolTableTestAgent extends Tool { public void run() { System.out.println("SASymbolTableTestAgent: starting"); - VM vm = VM.getVM(); - SymbolTable table = vm.getSymbolTable(); + try { + VM vm = VM.getVM(); + SymbolTable table = vm.getSymbolTable(); - // (a) These are names that are likely to exist in the symbol table - // of a JVM after start-up. They were taken from vmSymbols.hpp - // during the middle of JDK9 development. - // - // The purpose is not to check that each name must exist (a future - // version of JDK may not preload some of the classes). - // - // The purpose of this loops is to ensure that we check a lot of symbols, - // so we will (most likely) hit on both VALUE_ONLY_BUCKET_TYPE and normal bucket type - // in CompactHashTable.probe(). - for (String n : commonNames) { - Symbol s = table.probe(n); - System.out.format("%-40s = %s\n", n, s); - } + // (a) These are names that are likely to exist in the symbol table + // of a JVM after start-up. They were taken from vmSymbols.hpp + // during the middle of JDK9 development. + // + // The purpose is not to check that each name must exist (a future + // version of JDK may not preload some of the classes). + // + // The purpose of this loops is to ensure that we check a lot of symbols, + // so we will (most likely) hit on both VALUE_ONLY_BUCKET_TYPE and normal bucket type + // in CompactHashTable.probe(). + for (String n : commonNames) { + Symbol s = table.probe(n); + System.out.format("%-40s = %s\n", n, s); + } - System.out.println("======================================================================"); + System.out.println("======================================================================"); - // (b) Also test a few strings that are known to not exist in the table. This will - // both the compact table (if it exists) and the regular table to be walked. - for (String n : badNames) { - Symbol s = table.probe(n); - System.out.format("%-40s = %s\n", n, s); + // (b) Also test a few strings that are known to not exist in the table. This will + // both the compact table (if it exists) and the regular table to be walked. + for (String n : badNames) { + Symbol s = table.probe(n); + System.out.format("%-40s = %s\n", n, s); + } + } catch (NullPointerException e) { + System.out.println("connected too early -- please try again"); } } } diff --git a/hotspot/test/runtime/lambda-features/CyclicInterfaceInit.java b/hotspot/test/runtime/lambda-features/CyclicInterfaceInit.java new file mode 100644 index 00000000000..75fc5b03d95 --- /dev/null +++ b/hotspot/test/runtime/lambda-features/CyclicInterfaceInit.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8163969 + * @summary Interface initialization was crashing on this because the wrong class was getting + * initialization error. + * @run main CyclicInterfaceInit + */ +/** + * This snippet crashes with + * - Java(TM) SE Runtime Environment (8.0_101-b13) (build 1.8.0_101-b13) + */ +public class CyclicInterfaceInit { + + interface Base { + static final Object CONST = new Target(){}.someMethod(); + + default void important() { + // Super interfaces with default methods get initialized (JLS 12.4.1) + } + } + + static boolean out(String c) { + System.out.println("initializing " + c); + return true; + } + + interface Target extends Base { + boolean v = CyclicInterfaceInit.out("Target"); + default Object someMethod() { + throw new RuntimeException(); + } + // Target can be fully initialized before initializating Base because Target doesn't + // initiate the initialization of Base. + } + + static class InnerBad implements Target {} + + public static void main(String[] args) { + try { + new Target() {}; // Creates inner class that causes initialization of super interfaces + } catch (ExceptionInInitializerError e) { + System.out.println("ExceptionInInitializerError thrown as expected"); + } + // Try again, InnerBad instantiation should throw NoClassdefFoundError + // because Base is marked erroneous due to previous exception during initialization + try { + InnerBad ig = new InnerBad(); + throw new RuntimeException("FAILED- initialization of InnerBad should throw NCDFE"); + } catch (NoClassDefFoundError e) { + System.out.println("NoClassDefFoundError thrown as expected"); + } + // Target is already initialized. + System.out.println("Target.v is " + Target.v); + // shouldn't throw any exceptions. + } +} diff --git a/hotspot/test/runtime/lambda-features/InterfaceInitializationStates.java b/hotspot/test/runtime/lambda-features/InterfaceInitializationStates.java new file mode 100644 index 00000000000..e43bb808160 --- /dev/null +++ b/hotspot/test/runtime/lambda-features/InterfaceInitializationStates.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8163969 + * @summary Test interface initialization states and when certain interfaces are initialized + * in the presence of initialization errors. + * @run main InterfaceInitializationStates + */ + +import java.util.List; +import java.util.Arrays; +import java.util.ArrayList; + +public class InterfaceInitializationStates { + + static List> cInitOrder = new ArrayList<>(); + + // K interface with a default method has an initialization error + interface K { + boolean v = InterfaceInitializationStates.out(K.class); + static final Object CONST = InterfaceInitializationStates.someMethod(); + default int method() { return 2; } + } + + // I is initialized when CONST is used, and doesn't trigger initialization of K, + // I also doesn't get an initialization error just because K has an initialization error. + interface I extends K { + boolean v = InterfaceInitializationStates.out(I.class); + static final Object CONST = InterfaceInitializationStates.someMethod(); + } + + // L can be fully initialized even though it extends an interface that has an + // initialization error + interface L extends K { + boolean v = InterfaceInitializationStates.out(L.class); + default void lx() {} + static void func() { + System.out.println("Calling function on interface with bad super interface."); + } + } + + // Another interface needing initialization. + // Initialization of this interface does not occur with ClassLIM because K throws + // an initialization error, so the interface initialization is abandoned + interface M { + boolean v = InterfaceInitializationStates.out(M.class); + default void mx() {} + } + + static class ClassLIM implements L, I, M { + boolean v = InterfaceInitializationStates.out(ClassLIM.class); + int callMethodInK() { return method(); } + static { + // Since interface initialization of K fails, this should never be called + System.out.println("Initializing C, but L is still good"); + L.func(); + } + } + + // Finally initialize M + static class ClassM implements M { + boolean v = InterfaceInitializationStates.out(ClassM.class); + } + + // Iunlinked is testing initialization like interface I, except interface I is linked when + // ClassLIM is linked. + // Iunlinked is not linked already when K gets an initialization error. Linking Iunlinked + // should succeed and not get NoClassDefFoundError because it does not depend on the + // initialization state of K for linking. There's bug now where it gets this error. + // See: https://bugs.openjdk.java.net/browse/JDK-8166203. + interface Iunlinked extends K { + boolean v = InterfaceInitializationStates.out(Iunlinked.class); + } + + // More tests. What happens if we use K for parameters and return types? + // K is a symbolic reference in the constant pool and the initialization error only + // matters when it's used. + interface Iparams { + boolean v = InterfaceInitializationStates.out(Iparams.class); + K the_k = null; + K m(K k); // abstract + default K method() { return new K(){}; } + } + + static class ClassIparams implements Iparams { + boolean v = InterfaceInitializationStates.out(ClassIparams.class); + public K m(K k) { return k; } + } + + public static void main(java.lang.String[] unused) { + // The rule this tests is the last sentence of JLS 12.4.1: + + // When a class is initialized, its superclasses are initialized (if they have not + // been previously initialized), as well as any superinterfaces (s8.1.5) that declare any + // default methods (s9.4.3) (if they have not been previously initialized). Initialization + // of an interface does not, of itself, cause initialization of any of its superinterfaces. + + // Trigger initialization. + // Now L is fully_initialized even though K should + // throw an error during initialization. + boolean v = L.v; + L.func(); + + try { + ClassLIM c = new ClassLIM(); // is K initialized, with a perfectly good L in the middle + // was bug: this used to succeed and be able to callMethodInK(). + throw new RuntimeException("FAIL exception not thrown for class"); + } catch (ExceptionInInitializerError e) { + System.out.println("ExceptionInInitializerError thrown as expected"); + } + + // Test that K already has initialization error so gets ClassNotFoundException because + // initialization was attempted with ClassLIM. + try { + Class.forName("InterfaceInitializationStates$K", true, InterfaceInitializationStates.class.getClassLoader()); + throw new RuntimeException("FAIL exception not thrown for forName(K)"); + } catch(ClassNotFoundException e) { + throw new RuntimeException("ClassNotFoundException should not be thrown"); + } catch(NoClassDefFoundError e) { + System.out.println("NoClassDefFoundError thrown as expected"); + } + + new ClassM(); + + // Initialize I, which doesn't cause K (super interface) to be initialized. + // Since the initialization of I does _not_ cause K to be initialized, it does + // not get NoClassDefFoundError because K is erroneous. + // But the initialization of I throws RuntimeException, so we expect + // ExceptionInInitializerError. + try { + Object ii = I.CONST; + throw new RuntimeException("FAIL exception not thrown for I's initialization"); + } catch (ExceptionInInitializerError e) { + System.out.println("ExceptionInInitializerError as expected"); + } + + // Initialize Iunlinked. This should not get NoClassDefFoundError because K + // (its super interface) is in initialization_error state. + // This is a bug. It does now. + try { + boolean bb = Iunlinked.v; + throw new RuntimeException("FAIL exception not thrown for Iunlinked initialization"); + } catch(NoClassDefFoundError e) { + System.out.println("NoClassDefFoundError thrown because of bug"); + } + + // This should be okay + boolean value = Iparams.v; + System.out.println("value is " + value); + + ClassIparams p = new ClassIparams(); + try { + // Now we get an error because K got an initialization_error + K kk = p.method(); + throw new RuntimeException("FAIL exception not thrown for calling method for K"); + } catch(NoClassDefFoundError e) { + System.out.println("NoClassDefFoundError thrown as expected"); + } + + // Check expected class initialization order + List> expectedCInitOrder = Arrays.asList(L.class, K.class, M.class, ClassM.class, + I.class, Iparams.class, + ClassIparams.class); + if (!cInitOrder.equals(expectedCInitOrder)) { + throw new RuntimeException( + String.format("Class initialization array %s not equal to expected array %s", + cInitOrder, expectedCInitOrder)); + } + } + + static boolean out(Class c) { + System.out.println("#: initializing " + c.getName()); + cInitOrder.add(c); + return true; + } + static Object someMethod() { + throw new RuntimeException(); + } +} diff --git a/hotspot/test/runtime/modules/PatchModule/PatchModuleCDS.java b/hotspot/test/runtime/modules/PatchModule/PatchModuleCDS.java index a7f4784223b..82d5c385846 100644 --- a/hotspot/test/runtime/modules/PatchModule/PatchModuleCDS.java +++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleCDS.java @@ -23,41 +23,83 @@ /* * @test + * @summary test that --patch-module works with CDS * @library /test/lib * @modules java.base/jdk.internal.misc + * jdk.jartool/sun.tools.jar + * @build PatchModuleMain * @run main PatchModuleCDS */ import java.io.File; +import jdk.test.lib.InMemoryJavaCompiler; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; public class PatchModuleCDS { public static void main(String args[]) throws Throwable { - System.out.println("Test that --patch-module and -Xshare:dump are incompatibable"); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.naming=mods/java.naming", "-Xshare:dump"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldContain("Cannot use the following option when dumping the shared archive: --patch-module"); - System.out.println("Test that --patch-module and -Xshare:on are incompatibable"); + // Case 1: Test that --patch-module and -Xshare:dump are compatible String filename = "patch_module.jsa"; - pb = ProcessTools.createJavaProcessBuilder( + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=" + filename, - "-Xshare:dump"); - output = new OutputAnalyzer(pb.start()); - output.shouldContain("ro space:"); // Make sure archive got created. - - pb = ProcessTools.createJavaProcessBuilder( - "-XX:+UnlockDiagnosticVMOptions", - "-XX:SharedArchiveFile=" + filename, - "-Xshare:on", - "--patch-module=java.naming=mods/java.naming", + "-Xshare:dump", + "--patch-module=java.naming=no/such/directory", + "-Xlog:class+path=info", "-version"); - output = new OutputAnalyzer(pb.start()); - output.shouldContain("The shared archive file cannot be used with --patch-module"); + new OutputAnalyzer(pb.start()) + .shouldContain("ro space:"); // Make sure archive got created. - output.shouldHaveExitValue(1); + // Case 2: Test that only jar file in --patch-module is supported for CDS dumping + // Create a class file in the module java.base. + String source = "package javax.naming.spi; " + + "public class NamingManager { " + + " static { " + + " System.out.println(\"I pass!\"); " + + " } " + + "}"; + + ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager", + InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"), + System.getProperty("test.classes")); + + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedArchiveFile=" + filename, + "-Xshare:dump", + "--patch-module=java.base=" + System.getProperty("test.classes"), + "-Xlog:class+path=info", + "-version"); + new OutputAnalyzer(pb.start()) + .shouldContain("--patch-module requires a regular file during dumping"); + + // Case 3a: Test CDS dumping with jar file in --patch-module + BasicJarBuilder.build("javanaming", "javax/naming/spi/NamingManager"); + String moduleJar = BasicJarBuilder.getTestJar("javanaming.jar"); + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedArchiveFile=" + filename, + "-Xshare:dump", + "--patch-module=java.naming=" + moduleJar, + "-Xlog:class+load", + "-Xlog:class+path=info", + "PatchModuleMain", "javax.naming.spi.NamingManager"); + new OutputAnalyzer(pb.start()) + .shouldContain("ro space:"); // Make sure archive got created. + + // Case 3b: Test CDS run with jar file in --patch-module + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedArchiveFile=" + filename, + "-Xshare:auto", + "--patch-module=java.naming=" + moduleJar, + "-Xlog:class+load", + "-Xlog:class+path=info", + "PatchModuleMain", "javax.naming.spi.NamingManager"); + new OutputAnalyzer(pb.start()) + .shouldContain("I pass!") + .shouldHaveExitValue(0); } } diff --git a/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook/MAAClassFileLoadHook.java b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook/MAAClassFileLoadHook.java new file mode 100644 index 00000000000..0fa42bd599b --- /dev/null +++ b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook/MAAClassFileLoadHook.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @run main/othervm/native -agentlib:MAAClassFileLoadHook MAAClassFileLoadHook + * @run main/othervm/native -agentlib:MAAClassFileLoadHook=with_early_vmstart MAAClassFileLoadHook + * @run main/othervm/native -agentlib:MAAClassFileLoadHook=with_early_class_hook MAAClassFileLoadHook + * @run main/othervm/native -agentlib:MAAClassFileLoadHook=with_early_vmstart,with_early_class_hook MAAClassFileLoadHook + */ + +public class MAAClassFileLoadHook { + + static { + try { + System.loadLibrary("MAAClassFileLoadHook"); + } catch (UnsatisfiedLinkError ule) { + System.err.println("Could not load MAAClassFileLoadHook library"); + System.err.println("java.library.path: " + + System.getProperty("java.library.path")); + throw ule; + } + } + + native static int check(); + + public static void main(String args[]) { + int status = check(); + if (status != 0) { + throw new RuntimeException("Non-zero status returned from the agent: " + status); + } + } +} diff --git a/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook/libMAAClassFileLoadHook.c b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook/libMAAClassFileLoadHook.c new file mode 100644 index 00000000000..04ecb68867d --- /dev/null +++ b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook/libMAAClassFileLoadHook.c @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include "jvmti.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef JNI_ENV_ARG + +#ifdef __cplusplus +#define JNI_ENV_ARG(x, y) y +#define JNI_ENV_PTR(x) x +#else +#define JNI_ENV_ARG(x,y) x, y +#define JNI_ENV_PTR(x) (*x) +#endif + +#endif + +#define TranslateError(err) "JVMTI error" + +#define PASSED 0 +#define FAILED 2 + +static const char *EXPECTED_NAME = "java/util/Collections"; +static const char *EXC_CNAME = "java/lang/Exception"; + +static jvmtiEnv *jvmti = NULL; +static jint result = PASSED; +static jboolean printdump = JNI_FALSE; + +static jboolean with_early_vm_start_capability = JNI_FALSE; +static jboolean with_early_class_hook_capability = JNI_FALSE; + +static jboolean found_class_in_vm_start = JNI_FALSE; +static jboolean found_class_in_primordial = JNI_FALSE; +static jboolean found_class_in_cflh_events = JNI_FALSE; + +static int cflh_events_primordial_count = 0; +static int cflh_events_vm_start_count = 0; + +static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved); + +JNIEXPORT +jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { + return Agent_Initialize(jvm, options, reserved); +} + +JNIEXPORT +jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) { + return Agent_Initialize(jvm, options, reserved); +} + +JNIEXPORT +jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { + return JNI_VERSION_9; +} + +static +jint throw_exc(JNIEnv *env, char *msg) { + jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME)); + + if (exc_class == NULL) { + printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME); + return -1; + } + return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg); +} + +static void JNICALL +Callback_ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *env, + jclass class_being_redefined, + jobject loader, const char* name, jobject protection_domain, + jint class_data_len, const unsigned char* class_data, + jint *new_class_data_len, unsigned char** new_class_data) { + jvmtiPhase phase; + jvmtiError err; + + err = (*jvmti)->GetPhase(jvmti_env, &phase); + if (err != JVMTI_ERROR_NONE) { + printf("ClassFileLoadHook event: GetPhase error: %s (%d)\n", TranslateError(err), err); + result = FAILED; + return; + } + + if (phase == JVMTI_PHASE_PRIMORDIAL || phase == JVMTI_PHASE_START) { + if (phase == JVMTI_PHASE_START) { + cflh_events_vm_start_count++; + if(strcmp(name, EXPECTED_NAME) == 0) { + found_class_in_vm_start = JNI_TRUE; + } + } else { + cflh_events_primordial_count++; + if(strcmp(name, EXPECTED_NAME) == 0) { + found_class_in_primordial = JNI_TRUE; + } + } + } + + if(strcmp(name, EXPECTED_NAME) == 0) { + found_class_in_cflh_events = JNI_TRUE; + } + + if (printdump == JNI_TRUE) { + printf(">>> ClassFileLoadHook event: phase(%d), class name %s\n", phase, name); + } +} + +static +jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { + jint res, size; + jvmtiCapabilities caps; + jvmtiEventCallbacks callbacks; + jvmtiError err; + + if (options != NULL) { + if (strstr(options, "with_early_vmstart") != NULL) { + with_early_vm_start_capability = JNI_TRUE; + } + if (strstr(options, "with_early_class_hook") != NULL) { + with_early_class_hook_capability = JNI_TRUE; + } + if (strstr(options, "printdump") != NULL) { + printdump = JNI_TRUE; + } + } + + res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), + JVMTI_VERSION_9); + if (res != JNI_OK || jvmti == NULL) { + printf(" Error: wrong result of a valid call to GetEnv!\n"); + return JNI_ERR; + } + + printf("Enabling following capabilities: can_generate_all_class_hook_events"); + memset(&caps, 0, sizeof(caps)); + caps.can_generate_all_class_hook_events = 1; + if (with_early_vm_start_capability == JNI_TRUE) { + printf(", can_generate_early_vmstart"); + caps.can_generate_early_vmstart = 1; + } + if (with_early_class_hook_capability == JNI_TRUE) { + printf(", can_generate_early_class_hook_events"); + caps.can_generate_early_class_hook_events = 1; + } + printf("\n"); + + err = (*jvmti)->AddCapabilities(jvmti, &caps); + if (err != JVMTI_ERROR_NONE) { + printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err); + return JNI_ERR; + } + + size = (jint)sizeof(callbacks); + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.ClassFileLoadHook = Callback_ClassFileLoadHook; + + err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size); + if (err != JVMTI_ERROR_NONE) { + printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err); + return JNI_ERR; + } + + err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL); + if (err != JVMTI_ERROR_NONE) { + printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err); + return JNI_ERR; + } + + return JNI_OK; +} + +JNIEXPORT jint JNICALL +Java_MAAClassFileLoadHook_check(JNIEnv *env, jclass cls) { + jobject loader = NULL; + + if (jvmti == NULL) { + throw_exc(env, "JVMTI client was not properly loaded!\n"); + return FAILED; + } + + /* + * Expecting that we always get ClassFileLoadHook events in the VM Start phase. + */ + if (cflh_events_vm_start_count == 0) { + throw_exc(env, "Didn't get ClassFileLoadHook events in start phase!\n"); + return FAILED; + } + + if (with_early_class_hook_capability == JNI_TRUE) { + /* + * Expecting that we get ClassFileLoadHook events in the Primordial phase + * when can_generate_all_class_hook_events and can_generate_early_class_hook_events + * capabilities are enabled. + */ + if (cflh_events_primordial_count == 0) { + throw_exc(env, "Didn't get ClassFileLoadHook events in primordial phase!\n"); + return FAILED; + } + } else { + /* + * Expecting that we don't get ClassFileLoadHook events in the Primordial phase + * when can_generate_early_class_hook_events capability is disabled. + */ + if (cflh_events_primordial_count != 0) { + throw_exc(env, "Get ClassFileLoadHook events in primordial phase!\n"); + return FAILED; + } + } + + + if (with_early_vm_start_capability == JNI_TRUE) { + /* + * Expecting that "java/util/Collections" class from java.base module is present in the + * ClassFileLoadHook events during VM Start phase when can_generate_early_vmstart + * capability is enabled. + */ + printf("Expecting to find '%s' class in ClassFileLoadHook events during VM early start phase.\n", EXPECTED_NAME); + if (found_class_in_vm_start == JNI_FALSE) { + throw_exc(env, "Unable to find expected class in ClassLoad events during VM early start phase!\n"); + return FAILED; + } + } else if (with_early_class_hook_capability == JNI_TRUE) { + /* + * Expecting that "java/util/Collections" class from java.base module is present in the + * ClassFileLoadHook events during Primordial phase when can_generate_all_class_hook_events + * and can_generate_early_class_hook_events capabilities are enabled and can_generate_early_vmstart + * capability is disabled. + */ + printf("Expecting to find '%s' class in ClassFileLoadHook events during VM primordial phase.\n", EXPECTED_NAME); + if (found_class_in_primordial == JNI_FALSE) { + throw_exc(env, "Unable to find expected class in ClassFileLoadHook events during primordial phase!\n"); + return FAILED; + } + } else { + /* + * Expecting that "java/util/Collections" class from java.base module is not present in the + * ClassFileLoadHook events when can_generate_all_class_hook_events, can_generate_early_class_hook_events + * and can_generate_early_vmstart capabilities are disabled. + */ + printf("Expecting that '%s' class is absent in ClassLoadHook events.\n", EXPECTED_NAME); + if (found_class_in_cflh_events == JNI_TRUE) { + throw_exc(env, "Class is found in ClassFileLoadHook events!\n"); + return FAILED; + } + } + + return result; +} + +#ifdef __cplusplus +} +#endif diff --git a/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassLoadPrepare/MAAClassLoadPrepare.java b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassLoadPrepare/MAAClassLoadPrepare.java new file mode 100644 index 00000000000..98661c281c9 --- /dev/null +++ b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassLoadPrepare/MAAClassLoadPrepare.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8165681 + * @summary Verify ClassLoad and ClassPrepare JVMTI event with + * and without can_generate_early_vmstart capability + * @run main/othervm/native -agentlib:MAAClassLoadPrepare MAAClassLoadPrepare + * @run main/othervm/native -agentlib:MAAClassLoadPrepare=with_early_vmstart MAAClassLoadPrepare + */ + +public class MAAClassLoadPrepare { + + static { + try { + System.loadLibrary("MAAClassLoadPrepare"); + } catch (UnsatisfiedLinkError ule) { + System.err.println("Could not load MAAClassLoadPrepare library"); + System.err.println("java.library.path: " + + System.getProperty("java.library.path")); + throw ule; + } + } + + native static int check(); + + public static void main(String args[]) { + int status = check(); + if (status != 0) { + throw new RuntimeException("Non-zero status returned from the agent: " + status); + } + } +} diff --git a/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassLoadPrepare/libMAAClassLoadPrepare.c b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassLoadPrepare/libMAAClassLoadPrepare.c new file mode 100644 index 00000000000..dbfff1a15df --- /dev/null +++ b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassLoadPrepare/libMAAClassLoadPrepare.c @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include "jvmti.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef JNI_ENV_ARG + +#ifdef __cplusplus +#define JNI_ENV_ARG(x, y) y +#define JNI_ENV_PTR(x) x +#else +#define JNI_ENV_ARG(x,y) x, y +#define JNI_ENV_PTR(x) (*x) +#endif + +#endif + +#define TranslateError(err) "JVMTI error" + +#define PASSED 0 +#define FAILED 2 + +static const char *EXPECTED_SIGNATURE = "Ljava/util/Collections;"; +static const char *EXC_CNAME = "java/lang/Exception"; + +static jvmtiEnv *jvmti = NULL; +static jint result = PASSED; +static jboolean printdump = JNI_FALSE; + +static jboolean with_early_vm_start_capability = JNI_FALSE; + +static jboolean class_in_class_load_events_vm_start = JNI_FALSE; +static jboolean class_in_class_load_events_vm_live = JNI_FALSE; +static jboolean class_in_class_prepare_events_vm_start = JNI_FALSE; +static jboolean class_in_class_prepare_events_vm_live = JNI_FALSE; + +static int class_load_events_vm_start_count = 0; +static int class_prepare_events_vm_start_count = 0; + +static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved); + +JNIEXPORT +jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { + return Agent_Initialize(jvm, options, reserved); +} + +JNIEXPORT +jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) { + return Agent_Initialize(jvm, options, reserved); +} + +JNIEXPORT +jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { + return JNI_VERSION_9; +} + +static +jint throw_exc(JNIEnv *env, char *msg) { + jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME)); + + if (exc_class == NULL) { + printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME); + return -1; + } + return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg); +} + +static void JNICALL +Callback_ClassFileLoad(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread, jclass klass) { + jvmtiPhase phase; + char *sig, *generic; + jvmtiError err; + + err = (*jvmti)->GetPhase(jvmti_env,&phase); + if (err != JVMTI_ERROR_NONE) { + printf("ClassLoad event: GetPhase error: %s (%d)\n", TranslateError(err), err); + result = FAILED; + return; + } + + if (phase == JVMTI_PHASE_START || phase == JVMTI_PHASE_LIVE) { + + err = (*jvmti)->GetClassSignature(jvmti_env, klass, &sig, &generic); + + if (err != JVMTI_ERROR_NONE) { + printf("ClassLoad event: GetClassSignature error: %s (%d)\n", TranslateError(err), err); + result = FAILED; + return; + } + + if (phase == JVMTI_PHASE_START) { + class_load_events_vm_start_count++; + if(strcmp(sig, EXPECTED_SIGNATURE) == 0) { + class_in_class_load_events_vm_start = JNI_TRUE; + } + } else { + if(strcmp(sig, EXPECTED_SIGNATURE) == 0) { + class_in_class_load_events_vm_live = JNI_TRUE; + } + } + + if (printdump == JNI_TRUE) { + printf(">>> ClassLoad event: phase(%d), class signature %s\n", phase, sig == NULL ? "null": sig); + } + } else { + printf("ClassLoad event: get event in unexpected phase(%d)\n", phase); + result = FAILED; + } +} + +static void JNICALL +Callback_ClassFilePrepare(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread, jclass klass) { + jvmtiPhase phase; + char *sig, *generic; + jvmtiError err; + + err = (*jvmti)->GetPhase(jvmti_env,&phase); + if (err != JVMTI_ERROR_NONE) { + printf("ClassPrepare event: GetPhase error: %s (%d)\n", TranslateError(err), err); + result = FAILED; + return; + } + + if (phase == JVMTI_PHASE_START || phase == JVMTI_PHASE_LIVE) { + + err = (*jvmti)->GetClassSignature(jvmti_env, klass, &sig, &generic); + + if (err != JVMTI_ERROR_NONE) { + printf("ClassPrepare event: GetClassSignature error: %s (%d)\n", TranslateError(err), err); + result = FAILED; + return; + } + + if (phase == JVMTI_PHASE_START) { + class_prepare_events_vm_start_count++; + if(strcmp(sig, EXPECTED_SIGNATURE) == 0) { + class_in_class_prepare_events_vm_start = JNI_TRUE; + } + } else { + if(strcmp(sig, EXPECTED_SIGNATURE) == 0) { + class_in_class_prepare_events_vm_live = JNI_TRUE; + } + } + + if (printdump == JNI_TRUE) { + printf(">>> ClassPrepare event: phase(%d), class signature %s\n", phase, sig == NULL ? "null": sig); + } + } else { + printf("ClassPrepare event: get event in unexpected phase(%d)\n", phase); + result = FAILED; + } +} + +static +jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { + jint res, size; + jvmtiCapabilities caps; + jvmtiEventCallbacks callbacks; + jvmtiError err; + + if (options != NULL) { + if (strstr(options, "with_early_vmstart") != NULL) { + with_early_vm_start_capability = JNI_TRUE; + } + if (strstr(options, "printdump") != NULL) { + printdump = JNI_TRUE; + } + } + + res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), + JVMTI_VERSION_9); + if (res != JNI_OK || jvmti == NULL) { + printf(" Error: wrong result of a valid call to GetEnv!\n"); + return JNI_ERR; + } + + if (with_early_vm_start_capability == JNI_TRUE) { + printf("Enabling following capability: can_generate_early_vmstart\n"); + memset(&caps, 0, sizeof(caps)); + caps.can_generate_early_vmstart = 1; + + err = (*jvmti)->AddCapabilities(jvmti, &caps); + if (err != JVMTI_ERROR_NONE) { + printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err); + return JNI_ERR; + } + } + + size = (jint)sizeof(callbacks); + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.ClassLoad = Callback_ClassFileLoad; + callbacks.ClassPrepare = Callback_ClassFilePrepare; + + err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size); + if (err != JVMTI_ERROR_NONE) { + printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err); + return JNI_ERR; + } + + err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, NULL); + if (err != JVMTI_ERROR_NONE) { + printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err); + return JNI_ERR; + } + + err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL); + + if (err != JVMTI_ERROR_NONE) { + printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err); + return JNI_ERR; + } + + return JNI_OK; +} + +JNIEXPORT jint JNICALL +Java_MAAClassLoadPrepare_check(JNIEnv *env, jclass cls) { + jobject loader = NULL; + + if (jvmti == NULL) { + throw_exc(env, "JVMTI client was not properly loaded!\n"); + return FAILED; + } + + if (with_early_vm_start_capability == JNI_TRUE) { + /* + * Expecting that "java/util/Collections" class from java.base module is present in the + * ClassLoad and ClassPrepare events during VM Start phase when can_generate_early_vmstart + * capability is enabled. + * Expecting that ClassLoad and ClassPrepare events are sent in the VM early start phase + * when can_generate_early_vmstart is enabled(JDK-8165681). + */ + if (class_load_events_vm_start_count == 0) { + throw_exc(env, "Didn't get ClassLoad events in start phase!\n"); + return FAILED; + } + + printf("Expecting to find '%s' class in ClassLoad events during VM early start phase.\n", EXPECTED_SIGNATURE); + if (class_in_class_load_events_vm_start == JNI_FALSE) { + throw_exc(env, "Unable to find expected class in ClassLoad events during early start phase!\n"); + return FAILED; + } + + if (class_prepare_events_vm_start_count == 0) { + throw_exc(env, "Didn't get ClassPrepare events in start phase!\n"); + return FAILED; + } + + printf("Expecting to find '%s' class in ClassPrepare events during VM early start phase.\n", EXPECTED_SIGNATURE); + if (class_in_class_prepare_events_vm_start == JNI_FALSE) { + throw_exc(env, "Unable to find expected class in ClassPrepare events during early start phase!\n"); + return FAILED; + } + } else { + /* + * Expecting that "java/util/Collections" class from java.base module is not present in the + * ClassLoad and ClassPrepare events during VM Start phase when can_generate_early_vmstart + * capability is disabled. + */ + printf("Expecting that '%s' class is absent in ClassLoad events during normal VM start phase.\n", EXPECTED_SIGNATURE); + if (class_in_class_prepare_events_vm_start == JNI_TRUE) { + throw_exc(env, "Class is found in ClassLoad events during normal VM start phase!\n"); + return FAILED; + } + + printf("Expecting that '%s' class is absent in ClassPrepare events during normal VM start phase.\n", EXPECTED_SIGNATURE); + if (class_in_class_prepare_events_vm_start == JNI_TRUE) { + throw_exc(env, "Class is found in ClassPrepare events during normal VM start phase!\n"); + return FAILED; + } + } + + /* + * In any case, we not expect to see "java/util/Collections" class from java.base module + * in the ClassLoad and ClassPrepare events during VM Live phase. + */ + if (class_in_class_prepare_events_vm_live == JNI_TRUE) { + throw_exc(env, "Class is found in ClassLoad events during VM Live phase!\n"); + return FAILED; + } + + if (class_in_class_prepare_events_vm_live == JNI_TRUE) { + throw_exc(env, "Class is found in ClassPrepare events during VM Live phase!\n"); + return FAILED; + } + + return result; +} + +#ifdef __cplusplus +} +#endif diff --git a/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java new file mode 100644 index 00000000000..b8b76febb9c --- /dev/null +++ b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @summary Verify ThreadStart JVMTI event with can_generate_early_vmstart capability + * @run main/othervm/native -agentlib:MAAThreadStart MAAThreadStart + */ + +public class MAAThreadStart { + + static { + try { + System.loadLibrary("MAAThreadStart"); + } catch (UnsatisfiedLinkError ule) { + System.err.println("Could not load MAAThreadStart library"); + System.err.println("java.library.path: " + + System.getProperty("java.library.path")); + throw ule; + } + } + + native static int check(); + + public static void main(String args[]) { + int status = check(); + if (status != 0) { + throw new RuntimeException("Non-zero status returned from the agent: " + status); + } + } +} diff --git a/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ThreadStart/libMAAThreadStart.c b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ThreadStart/libMAAThreadStart.c new file mode 100644 index 00000000000..ea346536e42 --- /dev/null +++ b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ThreadStart/libMAAThreadStart.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include "jvmti.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef JNI_ENV_ARG + +#ifdef __cplusplus +#define JNI_ENV_ARG(x, y) y +#define JNI_ENV_PTR(x) x +#else +#define JNI_ENV_ARG(x,y) x, y +#define JNI_ENV_PTR(x) (*x) +#endif + +#endif + +#define TranslateError(err) "JVMTI error" + +#define PASSED 0 +#define FAILED 2 + +static const char *EXC_CNAME = "java/lang/Exception"; + +static jvmtiEnv *jvmti = NULL; +static jint result = PASSED; +static jboolean printdump = JNI_FALSE; + +static int thread_start_events_vm_start = 0; + +static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved); + +JNIEXPORT +jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { + return Agent_Initialize(jvm, options, reserved); +} + +JNIEXPORT +jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) { + return Agent_Initialize(jvm, options, reserved); +} + +JNIEXPORT +jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { + return JNI_VERSION_9; +} + +static +jint throw_exc(JNIEnv *env, char *msg) { + jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME)); + + if (exc_class == NULL) { + printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME); + return -1; + } + return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg); +} + + +void JNICALL Callback_ThreadStart(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread) { + jvmtiError err; + jvmtiPhase phase; + + err = (*jvmti)->GetPhase(jvmti_env,&phase); + if (err != JVMTI_ERROR_NONE) { + printf("ThreadStart event: GetPhase error: %s (%d)\n", TranslateError(err), err); + result = FAILED; + return; + } + + if (phase == JVMTI_PHASE_START) { + thread_start_events_vm_start++; + } + + if (printdump == JNI_TRUE) { + printf(">>> ThreadStart event: phase(%d)\n", phase); + } +} + +static +jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { + jint res, size; + jvmtiCapabilities caps; + jvmtiEventCallbacks callbacks; + jvmtiError err; + + if (options != NULL && strcmp(options, "printdump") == 0) { + printdump = JNI_TRUE; + } + + res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), + JVMTI_VERSION_9); + if (res != JNI_OK || jvmti == NULL) { + printf(" Error: wrong result of a valid call to GetEnv!\n"); + return JNI_ERR; + } + + printf("Enabling following capability: can_generate_early_vmstart\n"); + memset(&caps, 0, sizeof(caps)); + caps.can_generate_early_vmstart = 1; + + err = (*jvmti)->AddCapabilities(jvmti, &caps); + if (err != JVMTI_ERROR_NONE) { + printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err); + return JNI_ERR; + } + + size = (jint)sizeof(callbacks); + + memset(&callbacks, 0, sizeof(callbacks)); + callbacks.ThreadStart = Callback_ThreadStart; + + err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size); + if (err != JVMTI_ERROR_NONE) { + printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err); + return JNI_ERR; + } + + err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_THREAD_START, NULL); + if (err != JVMTI_ERROR_NONE) { + printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err); + return JNI_ERR; + } + + return JNI_OK; +} + +JNIEXPORT jint JNICALL +Java_MAAThreadStart_check(JNIEnv *env, jclass cls) { + jobject loader = NULL; + + if (jvmti == NULL) { + throw_exc(env, "JVMTI client was not properly loaded!\n"); + return FAILED; + } + + /* + * Expecting that ThreadStart events are sent during VM Start phase when + * can_generate_early_vmstart capability is enabled. + */ + if (thread_start_events_vm_start == 0) { + throw_exc(env, "Didn't get ThreadStart events in VM early start phase!\n"); + return FAILED; + } + + return result; +} + +#ifdef __cplusplus +} +#endif diff --git a/hotspot/test/serviceability/sa/LingeredAppWithDefaultMethods.java b/hotspot/test/serviceability/sa/LingeredAppWithDefaultMethods.java new file mode 100644 index 00000000000..83f45cbf51b --- /dev/null +++ b/hotspot/test/serviceability/sa/LingeredAppWithDefaultMethods.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.test.lib.apps.LingeredApp; + +interface Language { + static final long nbrOfWords = 99999; + public abstract long getNbrOfWords(); + default boolean hasScript() { + return true; + } +} + +class ParselTongue implements Language { + public long getNbrOfWords() { + return nbrOfWords * 4; + } +} + +class SlytherinSpeak extends ParselTongue { + public boolean hasScript() { + return false; + } +} + +public class LingeredAppWithDefaultMethods extends LingeredApp { + + public static void main(String args[]) { + ParselTongue lang = new ParselTongue(); + SlytherinSpeak slang = new SlytherinSpeak(); + System.out.println(lang.hasScript() || slang.hasScript()); + + LingeredApp.main(args); + } + } diff --git a/hotspot/test/serviceability/sa/TestDefaultMethods.java b/hotspot/test/serviceability/sa/TestDefaultMethods.java new file mode 100644 index 00000000000..cebd833c809 --- /dev/null +++ b/hotspot/test/serviceability/sa/TestDefaultMethods.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.ArrayList; +import java.util.List; + +import sun.jvm.hotspot.HotSpotAgent; +import sun.jvm.hotspot.utilities.SystemDictionaryHelper; +import sun.jvm.hotspot.oops.InstanceKlass; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.oops.Method; +import sun.jvm.hotspot.utilities.MethodArray; + +import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.Platform; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.Utils; +import jdk.test.lib.Asserts; + +/* + * @test + * @library /test/lib + * @requires os.family != "mac" + * @modules java.base/jdk.internal.misc + * jdk.hotspot.agent/sun.jvm.hotspot + * jdk.hotspot.agent/sun.jvm.hotspot.utilities + * jdk.hotspot.agent/sun.jvm.hotspot.oops + * jdk.hotspot.agent/sun.jvm.hotspot.debugger + * @run main/othervm TestDefaultMethods + */ + +public class TestDefaultMethods { + + private static LingeredAppWithDefaultMethods theApp = null; + + private static void printDefaultMethods(String pid, + String[] instanceKlassNames) { + HotSpotAgent agent = new HotSpotAgent(); + try { + agent.attach(Integer.parseInt(pid)); + } + catch (DebuggerException e) { + System.out.println(e.getMessage()); + System.err.println("Unable to connect to process ID: " + pid); + + agent.detach(); + e.printStackTrace(); + } + + for (String instanceKlassName : instanceKlassNames) { + InstanceKlass iKlass = SystemDictionaryHelper.findInstanceKlass(instanceKlassName); + MethodArray methods = iKlass.getMethods(); + MethodArray defaultMethods = iKlass.getDefaultMethods(); + for (int i = 0; i < methods.length(); i++) { + Method m = methods.at(i); + System.out.println("Method: " + m.getName().asString() + + " in instance klass: " + instanceKlassName); + } + if (defaultMethods != null) { + for (int j = 0; j < defaultMethods.length(); j++) { + Method dm = defaultMethods.at(j); + System.out.println("Default method: " + dm.getName().asString() + + " in instance klass: " + instanceKlassName); + } + } else { + System.out.println("No default methods in " + instanceKlassName); + } + + } + agent.detach(); + } + + private static void createAnotherToAttach( + String[] instanceKlassNames, + long lingeredAppPid) throws Exception { + + String[] toolArgs = { + "--add-modules=jdk.hotspot.agent", + "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED", + "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED", + "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED", + "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.debugger=ALL-UNNAMED", + "TestDefaultMethods", + Long.toString(lingeredAppPid) + }; + + // Start a new process to attach to the lingered app + ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(toolArgs); + OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder); + SAOutput.shouldHaveExitValue(0); + System.out.println(SAOutput.getOutput()); + + SAOutput.shouldContain( + "Default method: hasScript in instance klass: " + instanceKlassNames[1]); + SAOutput.shouldContain( + "No default methods in " + instanceKlassNames[0]); + SAOutput.shouldContain( + "Method: hasScript in instance klass: " + instanceKlassNames[0]); + SAOutput.shouldContain( + "No default methods in " + instanceKlassNames[2]); + } + + public static void main (String... args) throws Exception { + + String[] instanceKlassNames = new String[] { + "Language", + "ParselTongue", + "SlytherinSpeak" + }; + + if (!Platform.shouldSAAttach()) { + System.out.println( + "SA attach not expected to work - test skipped."); + return; + } + + if (args == null || args.length == 0) { + try { + List vmArgs = new ArrayList(); + vmArgs.add("-XX:+UsePerfData"); + vmArgs.addAll(Utils.getVmOptions()); + + theApp = new LingeredAppWithDefaultMethods(); + LingeredApp.startApp(vmArgs, theApp); + createAnotherToAttach(instanceKlassNames, + theApp.getPid()); + } finally { + LingeredApp.stopApp(theApp); + } + } else { + printDefaultMethods(args[0], instanceKlassNames); + } + } +} diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 0b75f1ff5b9..4468cfb7898 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -381,3 +381,4 @@ f695240370c77a25fed88225a392e7d530cb4d78 jdk-9+135 f1eafcb0eb7182b937bc93f214d8cabd01ec4d59 jdk-9+136 a8d5fe567ae72b4931040e59dd4478363f9004f5 jdk-9+137 69c3b12ba75b2e321dee731ac545e7fbff608451 jdk-9+138 +8991d71c5316bde259e6a417c1199b008ca3cdf0 jdk-9+139 diff --git a/jaxp/ASSEMBLY_EXCEPTION b/jaxp/ASSEMBLY_EXCEPTION index 8b7ac1d0813..065b8d90239 100644 --- a/jaxp/ASSEMBLY_EXCEPTION +++ b/jaxp/ASSEMBLY_EXCEPTION @@ -1,27 +1,27 @@ OPENJDK ASSEMBLY EXCEPTION -The OpenJDK source code made available by Sun at openjdk.java.net and -openjdk.dev.java.net ("OpenJDK Code") is distributed under the terms of the -GNU General Public License version 2 +The OpenJDK source code made available by Oracle America, Inc. (Oracle) at +openjdk.java.net ("OpenJDK Code") is distributed under the terms of the GNU +General Public License version 2 only ("GPL2"), with the following clarification and special exception. Linking this OpenJDK Code statically or dynamically with other code is making a combined work based on this library. Thus, the terms and conditions of GPL2 cover the whole combination. - As a special exception, Sun gives you permission to link this - OpenJDK Code with certain code licensed by Sun as indicated at + As a special exception, Oracle gives you permission to link this + OpenJDK Code with certain code licensed by Oracle as indicated at http://openjdk.java.net/legal/exception-modules-2007-05-08.html ("Designated Exception Modules") to produce an executable, regardless of the license terms of the Designated Exception Modules, and to copy and distribute the resulting executable under GPL2, provided that the Designated Exception Modules continue to be - governed by the licenses under which they were offered by Sun. + governed by the licenses under which they were offered by Oracle. -As such, it allows licensees and sublicensees of Sun's GPL2 OpenJDK Code to -build an executable that includes those portions of necessary code that Sun -could not provide under GPL2 (or that Sun has provided under GPL2 with the -Classpath exception). If you modify or add to the OpenJDK code, that new -GPL2 code may still be combined with Designated Exception Modules if the -new code is made subject to this exception by its copyright holder. +As such, it allows licensees and sublicensees of Oracle's GPL2 OpenJDK Code +to build an executable that includes those portions of necessary code that +Oracle could not provide under GPL2 (or that Oracle has provided under GPL2 +with the Classpath exception). If you modify or add to the OpenJDK code, +that new GPL2 code may still be combined with Designated Exception Modules +if the new code is made subject to this exception by its copyright holder. diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/validation/ValidationState.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/validation/ValidationState.java index c3a94519458..4013adb335c 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/validation/ValidationState.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/validation/ValidationState.java @@ -52,7 +52,7 @@ public class ValidationState implements ValidationContext { private SymbolTable fSymbolTable = null; private Locale fLocale = null; - private ArrayList fIdList; + private HashSet fIds; private ArrayList fIdRefList; // @@ -97,7 +97,7 @@ public class ValidationState implements ValidationContext { String key; for (int i = 0; i < fIdRefList.size(); i++) { key = fIdRefList.get(i); - if (fIdList == null || !fIdList.contains(key)) { + if (fIds == null || !fIds.contains(key)) { if (missingIDs == null) { missingIDs = new HashSet(); } @@ -112,7 +112,7 @@ public class ValidationState implements ValidationContext { fExtraChecking = true; fFacetChecking = true; fNamespaces = true; - fIdList = null; + fIds = null; fIdRefList = null; fEntityState = null; fNamespaceContext = null; @@ -126,7 +126,7 @@ public class ValidationState implements ValidationContext { * the two tables. */ public void resetIDTables() { - fIdList = null; + fIds = null; fIdRefList = null; } @@ -168,12 +168,11 @@ public class ValidationState implements ValidationContext { // id public boolean isIdDeclared(String name) { - if (fIdList == null) return false; - return fIdList.contains(name); + return fIds != null && fIds.contains(name); } public void addId(String name) { - if (fIdList == null) fIdList = new ArrayList(); - fIdList.add(name); + if (fIds == null) fIds = new HashSet<>(); + fIds.add(name); } // idref diff --git a/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLDOMWriterImpl.java b/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLDOMWriterImpl.java index c24e9cfcafe..67214d18001 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLDOMWriterImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLDOMWriterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package com.sun.xml.internal.stream.writers; +import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl; +import com.sun.org.apache.xerces.internal.dom.DocumentImpl; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import javax.xml.XMLConstants; @@ -57,7 +59,7 @@ import org.xml.sax.helpers.NamespaceSupport; * Change StringBuffer to StringBuilder, when JDK 1.5 will be minimum requirement for SJSXP. */ -public class XMLDOMWriterImpl implements XMLStreamWriter { +public class XMLDOMWriterImpl implements XMLStreamWriterBase { private Document ownerDoc = null; @@ -552,7 +554,7 @@ public class XMLDOMWriterImpl implements XMLStreamWriter { * @throws javax.xml.stream.XMLStreamException {@inheritDoc} */ public void writeStartDocument(String version) throws XMLStreamException { - ownerDoc.setXmlVersion(version); + writeStartDocument(null, version, false, false); } /** @@ -563,8 +565,20 @@ public class XMLDOMWriterImpl implements XMLStreamWriter { * @throws javax.xml.stream.XMLStreamException {@inheritDoc} */ public void writeStartDocument(String encoding, String version) throws XMLStreamException { + writeStartDocument(encoding, version, false, false); + } + + @Override + public void writeStartDocument(String encoding, String version, boolean standalone, boolean standaloneSet) throws XMLStreamException { + if (encoding != null && ownerDoc.getClass().isAssignableFrom(DocumentImpl.class)) { + ((DocumentImpl)ownerDoc).setXmlEncoding(encoding); + } + ownerDoc.setXmlVersion(version); - //TODO: What to do with encoding.-Venu + + if (standaloneSet) { + ownerDoc.setXmlStandalone(standalone); + } } /** diff --git a/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLEventWriterImpl.java b/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLEventWriterImpl.java index 8acbd32d162..75500e8965b 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLEventWriterImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLEventWriterImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,14 +49,14 @@ import javax.xml.stream.XMLStreamWriter; public class XMLEventWriterImpl implements XMLEventWriter{ //delegate everything to XMLStreamWriter.. - private XMLStreamWriter fStreamWriter ; + private final XMLStreamWriterBase fStreamWriter ; private static final boolean DEBUG = false; /** * * @param streamWriter */ public XMLEventWriterImpl(XMLStreamWriter streamWriter){ - fStreamWriter = streamWriter; + fStreamWriter = (XMLStreamWriterBase)streamWriter; } /** @@ -89,7 +89,8 @@ public class XMLEventWriterImpl implements XMLEventWriter{ StartDocument startDocument = (StartDocument)xMLEvent ; if (DEBUG)System.out.println("Adding StartDocument = " + startDocument.toString()); try { - fStreamWriter.writeStartDocument(startDocument.getCharacterEncodingScheme(), startDocument.getVersion()); + fStreamWriter.writeStartDocument(startDocument.getCharacterEncodingScheme(), startDocument.getVersion(), + startDocument.isStandalone(), startDocument.standaloneSet()); }catch(XMLStreamException e) { fStreamWriter.writeStartDocument(startDocument.getVersion()); } diff --git a/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLStreamWriterBase.java b/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLStreamWriterBase.java new file mode 100644 index 00000000000..56e66b740a2 --- /dev/null +++ b/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLStreamWriterBase.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.xml.internal.stream.writers; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +/** + * Base class for shared methods among XMLStreamWriter implementations. + */ +public interface XMLStreamWriterBase extends XMLStreamWriter { + /** + * Writes the XML declaration. + * + * @param encoding the specified encoding + * @param version the specified version + * @param standalone the flag indicating whether it is standalone + * @param standaloneSet the flag indicating whether the standalone attribute is set + * @throws XMLStreamException in case of an IOException + */ + public void writeStartDocument(String encoding, String version, + boolean standalone, boolean standaloneSet) + throws XMLStreamException; +} diff --git a/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLStreamWriterImpl.java b/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLStreamWriterImpl.java index f3b9b50397a..b7a0652087a 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLStreamWriterImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/xml/internal/stream/writers/XMLStreamWriterImpl.java @@ -71,7 +71,7 @@ import com.sun.xml.internal.stream.util.ReadOnlyIterator; * @author Santiago.Pericas-Geertsen@sun.com * @author Sunitha.Reddy@sun.com */ -public final class XMLStreamWriterImpl extends AbstractMap implements XMLStreamWriter { +public final class XMLStreamWriterImpl extends AbstractMap implements XMLStreamWriterBase { public static final String START_COMMENT = ""; @@ -1112,90 +1112,55 @@ public final class XMLStreamWriterImpl extends AbstractMap implements XMLStreamW } /** - * @throws XMLStreamException + * Writes the XML declaration. + * + * @throws XMLStreamException in case of an IOException */ public void writeStartDocument() throws XMLStreamException { - try { - fWriter.write(DEFAULT_XMLDECL); - } catch (IOException ex) { - throw new XMLStreamException(ex); - } + writeStartDocument(null, null, false, false); } /** - * @param version - * @throws XMLStreamException + * Writes the XML declaration. + * + * @param version the specified version + * @throws XMLStreamException in case of an IOException */ public void writeStartDocument(String version) throws XMLStreamException { - try { - if ((version == null) || version.equals("")) { - writeStartDocument(); - - return; - } - - fWriter.write(""); - } catch (IOException ex) { - throw new XMLStreamException(ex); - } + writeStartDocument(null, version, false, false); } /** - * @param encoding - * @param version - * @throws XMLStreamException + * Writes the XML declaration. + * + * @param encoding the specified encoding + * @param version the specified version + * @throws XMLStreamException in case of an IOException */ + @Override public void writeStartDocument(String encoding, String version) throws XMLStreamException { - //Revisit : What about standalone ? + writeStartDocument(encoding, version, false, false); + } + + @Override + public void writeStartDocument(String encoding, String version, + boolean standalone, boolean standaloneSet) + throws XMLStreamException { + try { - if ((encoding == null) && (version == null)) { - writeStartDocument(); - + if ((encoding == null || encoding.length() == 0) + && (version == null || version.length() == 0) + && (!standaloneSet)) { + fWriter.write(DEFAULT_XMLDECL); return; } - if (encoding == null) { - writeStartDocument(version); - - return; + // Verify the encoding before writing anything + if (encoding != null && !encoding.equals("")) { + verifyEncoding(encoding); } - String streamEncoding = null; - if (fWriter instanceof OutputStreamWriter) { - streamEncoding = ((OutputStreamWriter) fWriter).getEncoding(); - } - else if (fWriter instanceof UTF8OutputStreamWriter) { - streamEncoding = ((UTF8OutputStreamWriter) fWriter).getEncoding(); - } - else if (fWriter instanceof XMLWriter) { - streamEncoding = ((OutputStreamWriter) ((XMLWriter)fWriter).getWriter()).getEncoding(); - } - - if (streamEncoding != null && !streamEncoding.equalsIgnoreCase(encoding)) { - // If the equality check failed, check for charset encoding aliases - boolean foundAlias = false; - Set aliases = Charset.forName(encoding).aliases(); - for (Iterator it = aliases.iterator(); !foundAlias && it.hasNext(); ) { - if (streamEncoding.equalsIgnoreCase((String) it.next())) { - foundAlias = true; - } - } - // If no alias matches the encoding name, then report error - if (!foundAlias) { - throw new XMLStreamException("Underlying stream encoding '" - + streamEncoding - + "' and input paramter for writeStartDocument() method '" - + encoding + "' do not match."); - } - } - - fWriter.write(""); } catch (IOException ex) { throw new XMLStreamException(ex); } } + /** + * Verifies that the encoding is consistent between the underlying encoding + * and that specified. + * + * @param encoding the specified encoding + * @throws XMLStreamException if they do not match + */ + private void verifyEncoding(String encoding) throws XMLStreamException { + + String streamEncoding = null; + if (fWriter instanceof OutputStreamWriter) { + streamEncoding = ((OutputStreamWriter) fWriter).getEncoding(); + } + else if (fWriter instanceof UTF8OutputStreamWriter) { + streamEncoding = ((UTF8OutputStreamWriter) fWriter).getEncoding(); + } + else if (fWriter instanceof XMLWriter) { + streamEncoding = ((OutputStreamWriter) ((XMLWriter)fWriter).getWriter()).getEncoding(); + } + + if (streamEncoding != null && !streamEncoding.equalsIgnoreCase(encoding)) { + // If the equality check failed, check for charset encoding aliases + boolean foundAlias = false; + Set aliases = Charset.forName(encoding).aliases(); + for (Iterator it = aliases.iterator(); !foundAlias && it.hasNext(); ) { + if (streamEncoding.equalsIgnoreCase((String) it.next())) { + foundAlias = true; + } + } + // If no alias matches the encoding name, then report error + if (!foundAlias) { + throw new XMLStreamException("Underlying stream encoding '" + + streamEncoding + + "' and input paramter for writeStartDocument() method '" + + encoding + "' do not match."); + } + } + } + /** * @param localName * @throws XMLStreamException diff --git a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamWriterTest/XMLStreamWriterTest.java b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamWriterTest/XMLStreamWriterTest.java index 5b5893c8eb2..ff37bca192d 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamWriterTest/XMLStreamWriterTest.java +++ b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamWriterTest/XMLStreamWriterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,21 +20,29 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ - package stream.XMLStreamWriterTest; import java.io.StringWriter; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.stream.XMLEventFactory; +import javax.xml.stream.XMLEventWriter; import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; +import javax.xml.stream.events.XMLEvent; +import javax.xml.transform.dom.DOMResult; import org.testng.Assert; import org.testng.annotations.Listeners; import org.testng.annotations.Test; +import org.w3c.dom.Document; /* * @test - * @bug 6347190 + * @bug 6347190 8139584 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @run testng/othervm -DrunSecMngr=true stream.XMLStreamWriterTest.XMLStreamWriterTest * @run testng/othervm stream.XMLStreamWriterTest.XMLStreamWriterTest @@ -42,6 +50,48 @@ import org.testng.annotations.Test; */ @Listeners({jaxp.library.BasePolicy.class}) public class XMLStreamWriterTest { + /** + * @bug 8139584 + * Verifies that the resulting XML contains the standalone setting. + */ + @Test + public void testCreateStartDocument() throws XMLStreamException { + + StringWriter stringWriter = new StringWriter(); + XMLOutputFactory out = XMLOutputFactory.newInstance(); + XMLEventFactory eventFactory = XMLEventFactory.newInstance(); + + XMLEventWriter eventWriter = out.createXMLEventWriter(stringWriter); + + XMLEvent event = eventFactory.createStartDocument("iso-8859-15", "1.0", true); + eventWriter.add(event); + eventWriter.flush(); + Assert.assertTrue(stringWriter.toString().contains("encoding=\"iso-8859-15\"")); + Assert.assertTrue(stringWriter.toString().contains("version=\"1.0\"")); + Assert.assertTrue(stringWriter.toString().contains("standalone=\"yes\"")); + } + + /** + * @bug 8139584 + * Verifies that the resulting XML contains the standalone setting. + */ + @Test + public void testCreateStartDocument_DOMWriter() + throws ParserConfigurationException, XMLStreamException { + + XMLOutputFactory xof = XMLOutputFactory.newInstance(); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db = dbf.newDocumentBuilder(); + Document doc = db.newDocument(); + XMLEventWriter eventWriter = xof.createXMLEventWriter(new DOMResult(doc)); + XMLEventFactory eventFactory = XMLEventFactory.newInstance(); + XMLEvent event = eventFactory.createStartDocument("iso-8859-15", "1.0", true); + eventWriter.add(event); + eventWriter.flush(); + Assert.assertEquals(doc.getXmlEncoding(), "iso-8859-15"); + Assert.assertEquals(doc.getXmlVersion(), "1.0"); + Assert.assertTrue(doc.getXmlStandalone()); + } /** * Test of main method, of class TestXMLStreamWriter. diff --git a/jaxws/.hgtags b/jaxws/.hgtags index cada8dfb457..74e7eaf1dc5 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -384,3 +384,4 @@ ab1d78d395d4cb8be426ff181211da1a4085cf01 jdk-9+134 09ec13a99f50a4a346180d1e3b0fd8bc1ee399ce jdk-9+136 297c16d401c534cb879809d2a746d21ca99d2954 jdk-9+137 7d3a8f52b124db26ba8425c2931b748dd9d2791b jdk-9+138 +7a7aadf3c4500cc273c889aa1172d4fe3844bb6b jdk-9+139 diff --git a/jaxws/ASSEMBLY_EXCEPTION b/jaxws/ASSEMBLY_EXCEPTION index 8b7ac1d0813..065b8d90239 100644 --- a/jaxws/ASSEMBLY_EXCEPTION +++ b/jaxws/ASSEMBLY_EXCEPTION @@ -1,27 +1,27 @@ OPENJDK ASSEMBLY EXCEPTION -The OpenJDK source code made available by Sun at openjdk.java.net and -openjdk.dev.java.net ("OpenJDK Code") is distributed under the terms of the -GNU General Public License version 2 +The OpenJDK source code made available by Oracle America, Inc. (Oracle) at +openjdk.java.net ("OpenJDK Code") is distributed under the terms of the GNU +General Public License version 2 only ("GPL2"), with the following clarification and special exception. Linking this OpenJDK Code statically or dynamically with other code is making a combined work based on this library. Thus, the terms and conditions of GPL2 cover the whole combination. - As a special exception, Sun gives you permission to link this - OpenJDK Code with certain code licensed by Sun as indicated at + As a special exception, Oracle gives you permission to link this + OpenJDK Code with certain code licensed by Oracle as indicated at http://openjdk.java.net/legal/exception-modules-2007-05-08.html ("Designated Exception Modules") to produce an executable, regardless of the license terms of the Designated Exception Modules, and to copy and distribute the resulting executable under GPL2, provided that the Designated Exception Modules continue to be - governed by the licenses under which they were offered by Sun. + governed by the licenses under which they were offered by Oracle. -As such, it allows licensees and sublicensees of Sun's GPL2 OpenJDK Code to -build an executable that includes those portions of necessary code that Sun -could not provide under GPL2 (or that Sun has provided under GPL2 with the -Classpath exception). If you modify or add to the OpenJDK code, that new -GPL2 code may still be combined with Designated Exception Modules if the -new code is made subject to this exception by its copyright holder. +As such, it allows licensees and sublicensees of Oracle's GPL2 OpenJDK Code +to build an executable that includes those portions of necessary code that +Oracle could not provide under GPL2 (or that Oracle has provided under GPL2 +with the Classpath exception). If you modify or add to the OpenJDK code, +that new GPL2 code may still be combined with Designated Exception Modules +if the new code is made subject to this exception by its copyright holder. diff --git a/jdk/.hgtags b/jdk/.hgtags index 132fbb94863..3a9e6fe36d2 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -382,3 +382,4 @@ d5c70818cd8a82e76632c8c815bdb4f75f53aeaf jdk-9+132 e72df94364e3686e7d62059ce0d6b187b82da713 jdk-9+137 665096863382bf23ce891307cf2a7511e77c1c88 jdk-9+138 5518ac2f2ead5e594bd983f2047178136aafdfd0 jdk-9+139 +e93b7ea559759f036c9f69fd2ddaf47bb4e98385 jdk-9+140 diff --git a/jdk/make/CompileInterimRmic.gmk b/jdk/make/CompileInterimRmic.gmk index ce60127e6d1..9a30893f142 100644 --- a/jdk/make/CompileInterimRmic.gmk +++ b/jdk/make/CompileInterimRmic.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/CompileTools.gmk b/jdk/make/CompileTools.gmk index 46dab28f146..9d76d660e2d 100644 --- a/jdk/make/CompileTools.gmk +++ b/jdk/make/CompileTools.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/GenerateModuleSummary.gmk b/jdk/make/GenerateModuleSummary.gmk index 171183886a2..38d9985c263 100644 --- a/jdk/make/GenerateModuleSummary.gmk +++ b/jdk/make/GenerateModuleSummary.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/Tools.gmk b/jdk/make/Tools.gmk index 1034d34e15b..92af1ee102f 100644 --- a/jdk/make/Tools.gmk +++ b/jdk/make/Tools.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/gendata/GendataBreakIterator.gmk b/jdk/make/gendata/GendataBreakIterator.gmk index 2f7f5dff981..828e6314790 100644 --- a/jdk/make/gendata/GendataBreakIterator.gmk +++ b/jdk/make/gendata/GendataBreakIterator.gmk @@ -1,5 +1,5 @@ -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/gendata/GendataHtml32dtd.gmk b/jdk/make/gendata/GendataHtml32dtd.gmk index 0c18d2a280c..0189a7c081e 100644 --- a/jdk/make/gendata/GendataHtml32dtd.gmk +++ b/jdk/make/gendata/GendataHtml32dtd.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/gensrc/Gensrc-java.base.gmk b/jdk/make/gensrc/Gensrc-java.base.gmk index 66e41feb5e1..2a28382858e 100644 --- a/jdk/make/gensrc/Gensrc-java.base.gmk +++ b/jdk/make/gensrc/Gensrc-java.base.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/gensrc/Gensrc-jdk.jlink.gmk b/jdk/make/gensrc/Gensrc-jdk.jlink.gmk index c841345c737..9ac5b1918a2 100644 --- a/jdk/make/gensrc/Gensrc-jdk.jlink.gmk +++ b/jdk/make/gensrc/Gensrc-jdk.jlink.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/gensrc/GensrcIcons.gmk b/jdk/make/gensrc/GensrcIcons.gmk index 1970f18866b..62e31fb39f0 100644 --- a/jdk/make/gensrc/GensrcIcons.gmk +++ b/jdk/make/gensrc/GensrcIcons.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/gensrc/GensrcLocaleData.gmk b/jdk/make/gensrc/GensrcLocaleData.gmk index 0acc8f9591f..e7d19951cce 100644 --- a/jdk/make/gensrc/GensrcLocaleData.gmk +++ b/jdk/make/gensrc/GensrcLocaleData.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/gensrc/GensrcModuleLoaderMap.gmk b/jdk/make/gensrc/GensrcModuleLoaderMap.gmk index 859017d2a6d..365c83ddf90 100644 --- a/jdk/make/gensrc/GensrcModuleLoaderMap.gmk +++ b/jdk/make/gensrc/GensrcModuleLoaderMap.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/gensrc/GensrcVarHandles.gmk b/jdk/make/gensrc/GensrcVarHandles.gmk index b4a2bab9873..773c0f4c109 100644 --- a/jdk/make/gensrc/GensrcVarHandles.gmk +++ b/jdk/make/gensrc/GensrcVarHandles.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/launcher/Launcher-java.scripting.gmk b/jdk/make/launcher/Launcher-java.scripting.gmk index 18b8ad46d45..057d2bf3aca 100644 --- a/jdk/make/launcher/Launcher-java.scripting.gmk +++ b/jdk/make/launcher/Launcher-java.scripting.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/launcher/Launcher-jdk.compiler.gmk b/jdk/make/launcher/Launcher-jdk.compiler.gmk index 9c85acecdcc..5a1637d1dc0 100644 --- a/jdk/make/launcher/Launcher-jdk.compiler.gmk +++ b/jdk/make/launcher/Launcher-jdk.compiler.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/launcher/Launcher-jdk.javadoc.gmk b/jdk/make/launcher/Launcher-jdk.javadoc.gmk index 04bc99baf7e..534a9d97341 100644 --- a/jdk/make/launcher/Launcher-jdk.javadoc.gmk +++ b/jdk/make/launcher/Launcher-jdk.javadoc.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/launcher/Launcher-jdk.jdeps.gmk b/jdk/make/launcher/Launcher-jdk.jdeps.gmk index 4a69deede07..db29ecd88da 100644 --- a/jdk/make/launcher/Launcher-jdk.jdeps.gmk +++ b/jdk/make/launcher/Launcher-jdk.jdeps.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/launcher/Launcher-jdk.jlink.gmk b/jdk/make/launcher/Launcher-jdk.jlink.gmk index bd270b0dc0a..92cb61e5572 100644 --- a/jdk/make/launcher/Launcher-jdk.jlink.gmk +++ b/jdk/make/launcher/Launcher-jdk.jlink.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/launcher/Launcher-jdk.jstatd.gmk b/jdk/make/launcher/Launcher-jdk.jstatd.gmk index ee0ba2ad61d..aeb58557ff3 100644 --- a/jdk/make/launcher/Launcher-jdk.jstatd.gmk +++ b/jdk/make/launcher/Launcher-jdk.jstatd.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/launcher/Launcher-jdk.pack200.gmk b/jdk/make/launcher/Launcher-jdk.pack200.gmk index af050554a79..32b29b0c598 100644 --- a/jdk/make/launcher/Launcher-jdk.pack200.gmk +++ b/jdk/make/launcher/Launcher-jdk.pack200.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -58,10 +58,6 @@ else endif -ifeq ($(OPENJDK_TARGET_OS), solaris) - UNPACKEXE_TOOLCHAIN := TOOLCHAIN_LINK_CXX -endif - UNPACK_MAPFILE_DIR := $(JDK_TOPDIR)/make/mapfiles/libunpack UNPACK_MAPFILE_PLATFORM_FILE := \ $(UNPACK_MAPFILE_DIR)/mapfile-vers-unpack200-$(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH) @@ -79,7 +75,7 @@ endif $(eval $(call SetupNativeCompilation,BUILD_UNPACKEXE, \ SRC := $(UNPACKEXE_SRC), \ - TOOLCHAIN := $(UNPACKEXE_TOOLCHAIN), \ + TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ OPTIMIZATION := LOW, \ CFLAGS := $(UNPACKEXE_CFLAGS) $(CXXFLAGS_JDKEXE) -DFULL, \ CFLAGS_release := -DPRODUCT, \ diff --git a/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk b/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk index 5cb872ae5cf..82311e69fd6 100644 --- a/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk +++ b/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index a5417be9985..345c4253389 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -255,7 +255,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJIMAGE, \ CXXFLAGS := $(CXXFLAGS_JDKLIB) $(JIMAGELIB_CPPFLAGS), \ CFLAGS_unix := -UDEBUG, \ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjimage/mapfile-vers, \ - LDFLAGS := $(LDFLAGS_JDKLIB) \ + LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LDFLAGS_windows := -export:JIMAGE_Open -export:JIMAGE_Close \ -export:JIMAGE_PackageToModule \ diff --git a/jdk/make/lib/Lib-java.desktop.gmk b/jdk/make/lib/Lib-java.desktop.gmk index 5433fe96acb..1043ce777f2 100644 --- a/jdk/make/lib/Lib-java.desktop.gmk +++ b/jdk/make/lib/Lib-java.desktop.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/rmic/Rmic-java.management.gmk b/jdk/make/rmic/Rmic-java.management.gmk index 0452d5cbba5..0feaac3b88b 100644 --- a/jdk/make/rmic/Rmic-java.management.gmk +++ b/jdk/make/rmic/Rmic-java.management.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/rmic/RmicCommon.gmk b/jdk/make/rmic/RmicCommon.gmk index 611276ae467..bfc5b859b54 100644 --- a/jdk/make/rmic/RmicCommon.gmk +++ b/jdk/make/rmic/RmicCommon.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java index a108e467a33..9dd5b54c8cc 100644 --- a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java @@ -33,7 +33,6 @@ import java.nio.file.Paths; import java.security.AccessController; import java.security.Permission; import java.security.PrivilegedAction; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -333,7 +332,7 @@ public interface ModuleFinder { * *

When locating modules then any exceptions or errors thrown by the * {@code find} or {@code findAll} methods of the underlying module finders - * will be propogated to the caller of the resulting module finder's + * will be propagated to the caller of the resulting module finder's * {@code find} or {@code findAll} methods.

* * @param finders @@ -342,8 +341,8 @@ public interface ModuleFinder { * @return A {@code ModuleFinder} that composes a sequence of module finders */ static ModuleFinder compose(ModuleFinder... finders) { - final List finderList = Arrays.asList(finders); - finderList.forEach(Objects::requireNonNull); + // copy the list, also checking for nulls + final List finderList = List.of(finders); return new ModuleFinder() { private final Map nameToModule = new HashMap<>(); diff --git a/jdk/src/java.base/share/classes/java/net/CookieManager.java b/jdk/src/java.base/share/classes/java/net/CookieManager.java index fb3fa356e99..13ef9e468a0 100644 --- a/jdk/src/java.base/share/classes/java/net/CookieManager.java +++ b/jdk/src/java.base/share/classes/java/net/CookieManager.java @@ -81,7 +81,7 @@ import sun.util.logging.PlatformLogger; *
  • * Currently, only CookieStore.add(URI, HttpCookie) and CookieStore.get(URI) * are used by CookieManager. Others are for completeness and might be needed - * by a more sophisticated CookieStore implementation, e.g. a NetscapeCookieSotre. + * by a more sophisticated CookieStore implementation, e.g. a NetscapeCookieStore. *
  • * * @@ -201,10 +201,9 @@ public class CookieManager extends CookieHandler throw new IllegalArgumentException("Argument is null"); } - Map> cookieMap = new java.util.HashMap<>(); // if there's no default CookieStore, no way for us to get any cookie if (cookieJar == null) - return Collections.unmodifiableMap(cookieMap); + return Map.of(); boolean secureLink = "https".equalsIgnoreCase(uri.getScheme()); List cookies = new java.util.ArrayList<>(); @@ -244,8 +243,7 @@ public class CookieManager extends CookieHandler // apply sort rule (RFC 2965 sec. 3.3.4) List cookieHeader = sortByPath(cookies); - cookieMap.put("Cookie", cookieHeader); - return Collections.unmodifiableMap(cookieMap); + return Map.of("Cookie", cookieHeader); } public void diff --git a/jdk/src/java.base/share/classes/java/net/URLPermission.java b/jdk/src/java.base/share/classes/java/net/URLPermission.java index 0c38008cb13..e78c7aee68c 100644 --- a/jdk/src/java.base/share/classes/java/net/URLPermission.java +++ b/jdk/src/java.base/share/classes/java/net/URLPermission.java @@ -217,7 +217,7 @@ public final class URLPermission extends Permission { * where method-names is the list of methods separated by commas * and header-names is the list of permitted headers separated by commas. * There is no white space in the returned String. If header-names is empty - * then the colon separator will not be present. + * then the colon separator may not be present. */ public String getActions() { return actions; diff --git a/jdk/src/java.base/share/classes/java/nio/file/FileTreeIterator.java b/jdk/src/java.base/share/classes/java/nio/file/FileTreeIterator.java index 63b4dc767d8..c748e32571b 100644 --- a/jdk/src/java.base/share/classes/java/nio/file/FileTreeIterator.java +++ b/jdk/src/java.base/share/classes/java/nio/file/FileTreeIterator.java @@ -31,11 +31,10 @@ import java.io.UncheckedIOException; import java.util.Arrays; import java.util.Iterator; import java.util.NoSuchElementException; -import java.util.Objects; import java.nio.file.FileTreeWalker.Event; /** - * An {@code Iterator to iterate over the nodes of a file tree. + * An {@code Iterator} to iterate over the nodes of a file tree. * *
    {@code
      *     try (FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options)) {
    @@ -62,7 +61,7 @@ class FileTreeIterator implements Iterator, Closeable {
          * @throws  SecurityException
          *          if the security manager denies access to the starting file
          * @throws  NullPointerException
    -     *          if {@code start} or {@code options} is {@ocde null} or
    +     *          if {@code start} or {@code options} is {@code null} or
          *          the options array contains a {@code null} element
          */
         FileTreeIterator(Path start, int maxDepth, FileVisitOption... options)
    diff --git a/jdk/src/java.base/share/classes/java/nio/file/FileTreeWalker.java b/jdk/src/java.base/share/classes/java/nio/file/FileTreeWalker.java
    index 13bb629807f..b7dc93ad0f5 100644
    --- a/jdk/src/java.base/share/classes/java/nio/file/FileTreeWalker.java
    +++ b/jdk/src/java.base/share/classes/java/nio/file/FileTreeWalker.java
    @@ -171,7 +171,7 @@ class FileTreeWalker implements Closeable {
          *          if {@code options} contains an element that is not a
          *          {@code FileVisitOption}
          * @throws  NullPointerException
    -     *          if {@code options} is {@ocde null} or the options
    +     *          if {@code options} is {@code null} or the options
          *          array contains a {@code null} element
          */
         FileTreeWalker(Collection options, int maxDepth) {
    diff --git a/jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java b/jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java
    index 65ede7a2a83..096a7b48dc1 100644
    --- a/jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java
    +++ b/jdk/src/java.base/share/classes/java/security/KeyStoreSpi.java
    @@ -479,6 +479,10 @@ public abstract class KeyStoreSpi {
                 } else if (engineIsKeyEntry(alias)) {
                     KeyStore.PasswordProtection pp =
                             (KeyStore.PasswordProtection)protParam;
    +                if (pp.getProtectionAlgorithm() != null) {
    +                    throw new KeyStoreException(
    +                        "unsupported password protection algorithm");
    +                }
                     char[] password = pp.getPassword();
     
                     Key key = engineGetKey(alias, password);
    @@ -524,6 +528,10 @@ public abstract class KeyStoreSpi {
             KeyStore.PasswordProtection pProtect = null;
             if (protParam != null) {
                 pProtect = (KeyStore.PasswordProtection)protParam;
    +            if (pProtect.getProtectionAlgorithm() != null) {
    +                throw new KeyStoreException(
    +                    "unsupported password protection algorithm");
    +            }
             }
     
             // set entry
    diff --git a/jdk/src/java.base/share/classes/java/security/MessageDigest.java b/jdk/src/java.base/share/classes/java/security/MessageDigest.java
    index 3c08a64fbf8..b6959f5db4f 100644
    --- a/jdk/src/java.base/share/classes/java/security/MessageDigest.java
    +++ b/jdk/src/java.base/share/classes/java/security/MessageDigest.java
    @@ -32,10 +32,13 @@ import java.io.ByteArrayOutputStream;
     import java.io.PrintStream;
     import java.io.InputStream;
     import java.io.ByteArrayInputStream;
    -
    +import java.security.InvalidKeyException;
     import java.nio.ByteBuffer;
     
     import sun.security.util.Debug;
    +import sun.security.util.MessageDigestSpi2;
    +
    +import javax.crypto.SecretKey;
     
     /**
      * This MessageDigest class provides applications the functionality of a
    @@ -548,7 +551,7 @@ public abstract class MessageDigest extends MessageDigestSpi {
          * and its original parent (Object).
          */
     
    -    static class Delegate extends MessageDigest {
    +    static class Delegate extends MessageDigest implements MessageDigestSpi2 {
     
             // The provider implementation (delegate)
             private MessageDigestSpi digestSpi;
    @@ -601,6 +604,14 @@ public abstract class MessageDigest extends MessageDigestSpi {
                 digestSpi.engineUpdate(input);
             }
     
    +        public void engineUpdate(SecretKey key) throws InvalidKeyException {
    +            if (digestSpi instanceof MessageDigestSpi2) {
    +                ((MessageDigestSpi2)digestSpi).engineUpdate(key);
    +            } else {
    +                throw new UnsupportedOperationException
    +                ("Digest does not support update of SecretKey object");
    +            }
    +        }
             protected byte[] engineDigest() {
                 return digestSpi.engineDigest();
             }
    diff --git a/jdk/src/java.base/share/classes/java/security/Signature.java b/jdk/src/java.base/share/classes/java/security/Signature.java
    index 7efa9c9a7e6..9bfe4667df6 100644
    --- a/jdk/src/java.base/share/classes/java/security/Signature.java
    +++ b/jdk/src/java.base/share/classes/java/security/Signature.java
    @@ -37,7 +37,6 @@ import java.nio.ByteBuffer;
     import java.security.Provider.Service;
     
     import javax.crypto.Cipher;
    -import javax.crypto.CipherSpi;
     import javax.crypto.IllegalBlockSizeException;
     import javax.crypto.BadPaddingException;
     import javax.crypto.NoSuchPaddingException;
    @@ -180,15 +179,12 @@ public abstract class Signature extends SignatureSpi {
         private static final String RSA_CIPHER = "RSA/ECB/PKCS1Padding";
     
         // all the services we need to lookup for compatibility with Cipher
    -    private static final List rsaIds = Arrays.asList(
    -        new ServiceId[] {
    -            new ServiceId("Signature", "NONEwithRSA"),
    -            new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"),
    -            new ServiceId("Cipher", "RSA/ECB"),
    -            new ServiceId("Cipher", "RSA//PKCS1Padding"),
    -            new ServiceId("Cipher", "RSA"),
    -        }
    -    );
    +    private static final List rsaIds = List.of(
    +        new ServiceId("Signature", "NONEwithRSA"),
    +        new ServiceId("Cipher", "RSA/ECB/PKCS1Padding"),
    +        new ServiceId("Cipher", "RSA/ECB"),
    +        new ServiceId("Cipher", "RSA//PKCS1Padding"),
    +        new ServiceId("Cipher", "RSA"));
     
         /**
          * Returns a Signature object that implements the specified signature
    diff --git a/jdk/src/java.base/share/classes/java/time/Duration.java b/jdk/src/java.base/share/classes/java/time/Duration.java
    index e2c55a971ea..cacd3999a83 100644
    --- a/jdk/src/java.base/share/classes/java/time/Duration.java
    +++ b/jdk/src/java.base/share/classes/java/time/Duration.java
    @@ -88,8 +88,6 @@ import java.time.temporal.Temporal;
     import java.time.temporal.TemporalAmount;
     import java.time.temporal.TemporalUnit;
     import java.time.temporal.UnsupportedTemporalTypeException;
    -import java.util.Arrays;
    -import java.util.Collections;
     import java.util.List;
     import java.util.Objects;
     import java.util.regex.Matcher;
    @@ -578,8 +576,7 @@ public final class Duration
          * the simple initialization in Duration.
          */
         private static class DurationUnits {
    -        static final List UNITS =
    -                Collections.unmodifiableList(Arrays.asList(SECONDS, NANOS));
    +        static final List UNITS = List.of(SECONDS, NANOS);
         }
     
         //-----------------------------------------------------------------------
    diff --git a/jdk/src/java.base/share/classes/java/time/Period.java b/jdk/src/java.base/share/classes/java/time/Period.java
    index c7c04435262..e93d8a35d99 100644
    --- a/jdk/src/java.base/share/classes/java/time/Period.java
    +++ b/jdk/src/java.base/share/classes/java/time/Period.java
    @@ -83,8 +83,6 @@ import java.time.temporal.TemporalAmount;
     import java.time.temporal.TemporalQueries;
     import java.time.temporal.TemporalUnit;
     import java.time.temporal.UnsupportedTemporalTypeException;
    -import java.util.Arrays;
    -import java.util.Collections;
     import java.util.List;
     import java.util.Objects;
     import java.util.regex.Matcher;
    @@ -152,8 +150,7 @@ public final class Period
         /**
          * The set of supported units.
          */
    -    private static final List SUPPORTED_UNITS =
    -            Collections.unmodifiableList(Arrays.asList(YEARS, MONTHS, DAYS));
    +    private static final List SUPPORTED_UNITS = List.of(YEARS, MONTHS, DAYS);
     
         /**
          * The number of years.
    diff --git a/jdk/src/java.base/share/classes/java/time/ZoneId.java b/jdk/src/java.base/share/classes/java/time/ZoneId.java
    index bae99f601cc..5087888da4f 100644
    --- a/jdk/src/java.base/share/classes/java/time/ZoneId.java
    +++ b/jdk/src/java.base/share/classes/java/time/ZoneId.java
    @@ -76,14 +76,14 @@ import java.time.temporal.UnsupportedTemporalTypeException;
     import java.time.zone.ZoneRules;
     import java.time.zone.ZoneRulesException;
     import java.time.zone.ZoneRulesProvider;
    -import java.util.Collections;
    -import java.util.HashMap;
     import java.util.Locale;
     import java.util.Map;
     import java.util.Objects;
     import java.util.Set;
     import java.util.TimeZone;
     
    +import static java.util.Map.entry;
    +
     /**
      * A time-zone ID, such as {@code Europe/Paris}.
      * 

    @@ -220,39 +220,36 @@ public abstract class ZoneId implements Serializable { * * The map is unmodifiable. */ - public static final Map SHORT_IDS; - static { - Map map = new HashMap<>(64); - map.put("ACT", "Australia/Darwin"); - map.put("AET", "Australia/Sydney"); - map.put("AGT", "America/Argentina/Buenos_Aires"); - map.put("ART", "Africa/Cairo"); - map.put("AST", "America/Anchorage"); - map.put("BET", "America/Sao_Paulo"); - map.put("BST", "Asia/Dhaka"); - map.put("CAT", "Africa/Harare"); - map.put("CNT", "America/St_Johns"); - map.put("CST", "America/Chicago"); - map.put("CTT", "Asia/Shanghai"); - map.put("EAT", "Africa/Addis_Ababa"); - map.put("ECT", "Europe/Paris"); - map.put("IET", "America/Indiana/Indianapolis"); - map.put("IST", "Asia/Kolkata"); - map.put("JST", "Asia/Tokyo"); - map.put("MIT", "Pacific/Apia"); - map.put("NET", "Asia/Yerevan"); - map.put("NST", "Pacific/Auckland"); - map.put("PLT", "Asia/Karachi"); - map.put("PNT", "America/Phoenix"); - map.put("PRT", "America/Puerto_Rico"); - map.put("PST", "America/Los_Angeles"); - map.put("SST", "Pacific/Guadalcanal"); - map.put("VST", "Asia/Ho_Chi_Minh"); - map.put("EST", "-05:00"); - map.put("MST", "-07:00"); - map.put("HST", "-10:00"); - SHORT_IDS = Collections.unmodifiableMap(map); - } + public static final Map SHORT_IDS = Map.ofEntries( + entry("ACT", "Australia/Darwin"), + entry("AET", "Australia/Sydney"), + entry("AGT", "America/Argentina/Buenos_Aires"), + entry("ART", "Africa/Cairo"), + entry("AST", "America/Anchorage"), + entry("BET", "America/Sao_Paulo"), + entry("BST", "Asia/Dhaka"), + entry("CAT", "Africa/Harare"), + entry("CNT", "America/St_Johns"), + entry("CST", "America/Chicago"), + entry("CTT", "Asia/Shanghai"), + entry("EAT", "Africa/Addis_Ababa"), + entry("ECT", "Europe/Paris"), + entry("IET", "America/Indiana/Indianapolis"), + entry("IST", "Asia/Kolkata"), + entry("JST", "Asia/Tokyo"), + entry("MIT", "Pacific/Apia"), + entry("NET", "Asia/Yerevan"), + entry("NST", "Pacific/Auckland"), + entry("PLT", "Asia/Karachi"), + entry("PNT", "America/Phoenix"), + entry("PRT", "America/Puerto_Rico"), + entry("PST", "America/Los_Angeles"), + entry("SST", "Pacific/Guadalcanal"), + entry("VST", "Asia/Ho_Chi_Minh"), + entry("EST", "-05:00"), + entry("MST", "-07:00"), + entry("HST", "-10:00") + ); /** * Serialization version. */ diff --git a/jdk/src/java.base/share/classes/java/time/chrono/ChronoPeriodImpl.java b/jdk/src/java.base/share/classes/java/time/chrono/ChronoPeriodImpl.java index 911144d5b04..646af14d05a 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/ChronoPeriodImpl.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/ChronoPeriodImpl.java @@ -77,8 +77,6 @@ import java.time.temporal.TemporalQueries; import java.time.temporal.TemporalUnit; import java.time.temporal.UnsupportedTemporalTypeException; import java.time.temporal.ValueRange; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Objects; @@ -105,8 +103,7 @@ final class ChronoPeriodImpl /** * The set of supported units. */ - private static final List SUPPORTED_UNITS = - Collections.unmodifiableList(Arrays.asList(YEARS, MONTHS, DAYS)); + private static final List SUPPORTED_UNITS = List.of(YEARS, MONTHS, DAYS); /** * The chronology. diff --git a/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java b/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java index ebe4e8a29d4..d61c2333303 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java @@ -59,10 +59,7 @@ package java.time.chrono; import static java.time.temporal.ChronoField.EPOCH_DAY; -import java.io.File; -import java.io.FileInputStream; import java.io.FilePermission; -import java.io.IOException; import java.io.InputStream; import java.io.InvalidObjectException; import java.io.ObjectInputStream; @@ -83,7 +80,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Properties; import sun.util.logging.PlatformLogger; @@ -512,7 +508,7 @@ public final class HijrahChronology extends AbstractChronology implements Serial @Override public List eras() { - return Arrays.asList(HijrahEra.values()); + return List.of(HijrahEra.values()); } //----------------------------------------------------------------------- diff --git a/jdk/src/java.base/share/classes/java/time/chrono/IsoChronology.java b/jdk/src/java.base/share/classes/java/time/chrono/IsoChronology.java index 7ce8e4ba21a..4919b3d7d3a 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/IsoChronology.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/IsoChronology.java @@ -90,7 +90,6 @@ import java.time.temporal.ChronoField; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; import java.time.temporal.ValueRange; -import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Map; @@ -492,7 +491,7 @@ public final class IsoChronology extends AbstractChronology implements Serializa @Override public List eras() { - return Arrays.asList(IsoEra.values()); + return List.of(IsoEra.values()); } //----------------------------------------------------------------------- diff --git a/jdk/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java b/jdk/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java index 2bd38c8d755..4478c4c7de1 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/JapaneseChronology.java @@ -81,7 +81,6 @@ import java.time.temporal.TemporalAdjusters; import java.time.temporal.TemporalField; import java.time.temporal.UnsupportedTemporalTypeException; import java.time.temporal.ValueRange; -import java.util.Arrays; import java.util.Calendar; import java.util.List; import java.util.Locale; @@ -379,7 +378,7 @@ public final class JapaneseChronology extends AbstractChronology implements Seri @Override public List eras() { - return Arrays.asList(JapaneseEra.values()); + return List.of(JapaneseEra.values()); } JapaneseEra getCurrentEra() { diff --git a/jdk/src/java.base/share/classes/java/time/chrono/MinguoChronology.java b/jdk/src/java.base/share/classes/java/time/chrono/MinguoChronology.java index 8159adc0ac5..fd6fdc3e8cd 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/MinguoChronology.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/MinguoChronology.java @@ -72,7 +72,6 @@ import java.time.temporal.ChronoField; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalField; import java.time.temporal.ValueRange; -import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.Map; @@ -306,7 +305,7 @@ public final class MinguoChronology extends AbstractChronology implements Serial @Override public List eras() { - return Arrays.asList(MinguoEra.values()); + return List.of(MinguoEra.values()); } //----------------------------------------------------------------------- diff --git a/jdk/src/java.base/share/classes/java/time/chrono/ThaiBuddhistChronology.java b/jdk/src/java.base/share/classes/java/time/chrono/ThaiBuddhistChronology.java index 6412c9dab15..c6938b2c530 100644 --- a/jdk/src/java.base/share/classes/java/time/chrono/ThaiBuddhistChronology.java +++ b/jdk/src/java.base/share/classes/java/time/chrono/ThaiBuddhistChronology.java @@ -342,7 +342,7 @@ public final class ThaiBuddhistChronology extends AbstractChronology implements @Override public List eras() { - return Arrays.asList(ThaiBuddhistEra.values()); + return List.of(ThaiBuddhistEra.values()); } //----------------------------------------------------------------------- diff --git a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java index ec5fd9c8086..a3f903a7d9a 100644 --- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java +++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java @@ -1685,6 +1685,7 @@ public final class DateTimeFormatter { public DateTimeFormatter withResolverFields(TemporalField... resolverFields) { Set fields = null; if (resolverFields != null) { + // Set.of cannot be used because it is hostile to nulls and duplicate elements fields = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(resolverFields))); } if (Objects.equals(this.resolverFields, fields)) { diff --git a/jdk/src/java.base/share/classes/java/time/zone/ZoneOffsetTransition.java b/jdk/src/java.base/share/classes/java/time/zone/ZoneOffsetTransition.java index c1568e46364..94264f32cce 100644 --- a/jdk/src/java.base/share/classes/java/time/zone/ZoneOffsetTransition.java +++ b/jdk/src/java.base/share/classes/java/time/zone/ZoneOffsetTransition.java @@ -387,9 +387,9 @@ public final class ZoneOffsetTransition */ List getValidOffsets() { if (isGap()) { - return Collections.emptyList(); + return List.of(); } - return Arrays.asList(getOffsetBefore(), getOffsetAfter()); + return List.of(getOffsetBefore(), getOffsetAfter()); } //----------------------------------------------------------------------- diff --git a/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java b/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java index f6154857b8d..ed2330f38ef 100644 --- a/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java +++ b/jdk/src/java.base/share/classes/java/time/zone/ZoneRules.java @@ -303,7 +303,6 @@ public final class ZoneRules implements Serializable { * Creates an instance of ZoneRules that has fixed zone rules. * * @param offset the offset this fixed zone rules is based on, not null - * @return the zone rules, not null * @see #isFixedOffset() */ private ZoneRules(ZoneOffset offset) { @@ -970,7 +969,7 @@ public final class ZoneRules implements Serializable { * @return an immutable list of transition rules, not null */ public List getTransitionRules() { - return Collections.unmodifiableList(Arrays.asList(lastRules)); + return List.of(lastRules); } /** diff --git a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java b/jdk/src/java.base/share/classes/java/util/ResourceBundle.java index bc7aaae063e..1d84e2dee6b 100644 --- a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java +++ b/jdk/src/java.base/share/classes/java/util/ResourceBundle.java @@ -2491,34 +2491,29 @@ public abstract class ResourceBundle { /** * The default format List, which contains the strings * "java.class" and "java.properties", in - * this order. This List is {@linkplain - * Collections#unmodifiableList(List) unmodifiable}. + * this order. This List is unmodifiable. * * @see #getFormats(String) */ public static final List FORMAT_DEFAULT - = Collections.unmodifiableList(Arrays.asList("java.class", - "java.properties")); + = List.of("java.class", "java.properties"); /** * The class-only format List containing - * "java.class". This List is {@linkplain - * Collections#unmodifiableList(List) unmodifiable}. + * "java.class". This List is unmodifiable. * * @see #getFormats(String) */ - public static final List FORMAT_CLASS - = Collections.unmodifiableList(Arrays.asList("java.class")); + public static final List FORMAT_CLASS = List.of("java.class"); /** * The properties-only format List containing - * "java.properties". This List is - * {@linkplain Collections#unmodifiableList(List) unmodifiable}. + * "java.properties". This List is unmodifiable. * * @see #getFormats(String) */ public static final List FORMAT_PROPERTIES - = Collections.unmodifiableList(Arrays.asList("java.properties")); + = List.of("java.properties"); /** * The time-to-live constant for not caching loaded resource bundle diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java index 9410db99bc4..1284e00afb7 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java @@ -108,16 +108,40 @@ public class AtomicBoolean implements java.io.Serializable { * if the current value {@code == expectedValue}, * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. * + * @deprecated This method has plain memory effects but the method + * name implies volatile memory effects (see methods such as + * {@link #compareAndExchange} and {@link #compareAndSet}). To avoid + * confusion over plain or volatile memory effects it is recommended that + * the method {@link #weakCompareAndSetPlain} be used instead. + * * @param expectedValue the expected value * @param newValue the new value * @return {@code true} if successful + * @see #weakCompareAndSetPlain */ + @Deprecated(since="9") public boolean weakCompareAndSet(boolean expectedValue, boolean newValue) { return VALUE.weakCompareAndSetPlain(this, (expectedValue ? 1 : 0), (newValue ? 1 : 0)); } + /** + * Possibly atomically sets the value to {@code newValue} + * if the current value {@code == expectedValue}, + * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. + * + * @param expectedValue the expected value + * @param newValue the new value + * @return {@code true} if successful + * @since 9 + */ + public boolean weakCompareAndSetPlain(boolean expectedValue, boolean newValue) { + return VALUE.weakCompareAndSetPlain(this, + (expectedValue ? 1 : 0), + (newValue ? 1 : 0)); + } + /** * Sets the value to {@code newValue}, * with memory effects as specified by {@link VarHandle#setVolatile}. diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java index 4e4c51eb53a..f2184aaeebd 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java @@ -148,14 +148,36 @@ public class AtomicInteger extends Number implements java.io.Serializable { * if the current value {@code == expectedValue}, * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. * + * @deprecated This method has plain memory effects but the method + * name implies volatile memory effects (see methods such as + * {@link #compareAndExchange} and {@link #compareAndSet}). To avoid + * confusion over plain or volatile memory effects it is recommended that + * the method {@link #weakCompareAndSetPlain} be used instead. + * * @param expectedValue the expected value * @param newValue the new value * @return {@code true} if successful + * @see #weakCompareAndSetPlain */ + @Deprecated(since="9") public final boolean weakCompareAndSet(int expectedValue, int newValue) { return U.weakCompareAndSwapInt(this, VALUE, expectedValue, newValue); } + /** + * Possibly atomically sets the value to {@code newValue} + * if the current value {@code == expectedValue}, + * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. + * + * @param expectedValue the expected value + * @param newValue the new value + * @return {@code true} if successful + * @since 9 + */ + public final boolean weakCompareAndSetPlain(int expectedValue, int newValue) { + return U.weakCompareAndSwapInt(this, VALUE, expectedValue, newValue); + } + /** * Atomically increments the current value, * with memory effects as specified by {@link VarHandle#getAndAdd}. diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java index 8bce29b6f95..efddc9fb0f4 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java @@ -151,15 +151,38 @@ public class AtomicIntegerArray implements java.io.Serializable { * {@code newValue} if the element's current value {@code == expectedValue}, * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. * + * @deprecated This method has plain memory effects but the method + * name implies volatile memory effects (see methods such as + * {@link #compareAndExchange} and {@link #compareAndSet}). To avoid + * confusion over plain or volatile memory effects it is recommended that + * the method {@link #weakCompareAndSetPlain} be used instead. + * * @param i the index * @param expectedValue the expected value * @param newValue the new value * @return {@code true} if successful + * @see #weakCompareAndSetPlain */ + @Deprecated(since="9") public final boolean weakCompareAndSet(int i, int expectedValue, int newValue) { return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue); } + /** + * Possibly atomically sets the element at index {@code i} to + * {@code newValue} if the element's current value {@code == expectedValue}, + * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. + * + * @param i the index + * @param expectedValue the expected value + * @param newValue the new value + * @return {@code true} if successful + * @since 9 + */ + public final boolean weakCompareAndSetPlain(int i, int expectedValue, int newValue) { + return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue); + } + /** * Atomically increments the value of the element at index {@code i}, * with memory effects as specified by {@link VarHandle#getAndAdd}. diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java index 5ee7104fdb8..a0670eeac8f 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java @@ -164,14 +164,36 @@ public class AtomicLong extends Number implements java.io.Serializable { * if the current value {@code == expectedValue}, * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. * + * @deprecated This method has plain memory effects but the method + * name implies volatile memory effects (see methods such as + * {@link #compareAndExchange} and {@link #compareAndSet}). To avoid + * confusion over plain or volatile memory effects it is recommended that + * the method {@link #weakCompareAndSetPlain} be used instead. + * * @param expectedValue the expected value * @param newValue the new value * @return {@code true} if successful + * @see #weakCompareAndSetPlain */ + @Deprecated(since="9") public final boolean weakCompareAndSet(long expectedValue, long newValue) { return U.weakCompareAndSwapLong(this, VALUE, expectedValue, newValue); } + /** + * Possibly atomically sets the value to {@code newValue} + * if the current value {@code == expectedValue}, + * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. + * + * @param expectedValue the expected value + * @param newValue the new value + * @return {@code true} if successful + * @since 9 + */ + public final boolean weakCompareAndSetPlain(long expectedValue, long newValue) { + return U.weakCompareAndSwapLong(this, VALUE, expectedValue, newValue); + } + /** * Atomically increments the current value, * with memory effects as specified by {@link VarHandle#getAndAdd}. diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java index 84182c44f74..10aa9deea83 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java @@ -151,15 +151,38 @@ public class AtomicLongArray implements java.io.Serializable { * {@code newValue} if the element's current value {@code == expectedValue}, * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. * + * @deprecated This method has plain memory effects but the method + * name implies volatile memory effects (see methods such as + * {@link #compareAndExchange} and {@link #compareAndSet}). To avoid + * confusion over plain or volatile memory effects it is recommended that + * the method {@link #weakCompareAndSetPlain} be used instead. + * * @param i the index * @param expectedValue the expected value * @param newValue the new value * @return {@code true} if successful + * @see #weakCompareAndSetPlain */ + @Deprecated(since="9") public final boolean weakCompareAndSet(int i, long expectedValue, long newValue) { return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue); } + /** + * Possibly atomically sets the element at index {@code i} to + * {@code newValue} if the element's current value {@code == expectedValue}, + * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. + * + * @param i the index + * @param expectedValue the expected value + * @param newValue the new value + * @return {@code true} if successful + * @since 9 + */ + public final boolean weakCompareAndSetPlain(int i, long expectedValue, long newValue) { + return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue); + } + /** * Atomically increments the value of the element at index {@code i}, * with memory effects as specified by {@link VarHandle#getAndAdd}. diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java index 0098d31bf2e..66b7b6c37a5 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java @@ -127,14 +127,36 @@ public class AtomicReference implements java.io.Serializable { * if the current value {@code == expectedValue}, * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. * + * @deprecated This method has plain memory effects but the method + * name implies volatile memory effects (see methods such as + * {@link #compareAndExchange} and {@link #compareAndSet}). To avoid + * confusion over plain or volatile memory effects it is recommended that + * the method {@link #weakCompareAndSetPlain} be used instead. + * * @param expectedValue the expected value * @param newValue the new value * @return {@code true} if successful + * @see #weakCompareAndSetPlain */ + @Deprecated(since="9") public final boolean weakCompareAndSet(V expectedValue, V newValue) { return VALUE.weakCompareAndSetPlain(this, expectedValue, newValue); } + /** + * Possibly atomically sets the value to {@code newValue} + * if the current value {@code == expectedValue}, + * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. + * + * @param expectedValue the expected value + * @param newValue the new value + * @return {@code true} if successful + * @since 9 + */ + public final boolean weakCompareAndSetPlain(V expectedValue, V newValue) { + return VALUE.weakCompareAndSetPlain(this, expectedValue, newValue); + } + /** * Atomically sets the value to {@code newValue} and returns the old value, * with memory effects as specified by {@link VarHandle#getAndSet}. diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java index 998f167d5cc..2d529bb7ef1 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java @@ -157,15 +157,38 @@ public class AtomicReferenceArray implements java.io.Serializable { * {@code newValue} if the element's current value {@code == expectedValue}, * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. * + * @deprecated This method has plain memory effects but the method + * name implies volatile memory effects (see methods such as + * {@link #compareAndExchange} and {@link #compareAndSet}). To avoid + * confusion over plain or volatile memory effects it is recommended that + * the method {@link #weakCompareAndSetPlain} be used instead. + * * @param i the index * @param expectedValue the expected value * @param newValue the new value * @return {@code true} if successful + * @see #weakCompareAndSetPlain */ + @Deprecated(since="9") public final boolean weakCompareAndSet(int i, E expectedValue, E newValue) { return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue); } + /** + * Possibly atomically sets the element at index {@code i} to + * {@code newValue} if the element's current value {@code == expectedValue}, + * with memory effects as specified by {@link VarHandle#weakCompareAndSetPlain}. + * + * @param i the index + * @param expectedValue the expected value + * @param newValue the new value + * @return {@code true} if successful + * @since 9 + */ + public final boolean weakCompareAndSetPlain(int i, E expectedValue, E newValue) { + return AA.weakCompareAndSetPlain(array, i, expectedValue, newValue); + } + /** * Atomically updates the element at index {@code i} with the results * of applying the given function, returning the previous value. The diff --git a/jdk/src/java.base/share/classes/java/util/spi/ToolProvider.java b/jdk/src/java.base/share/classes/java/util/spi/ToolProvider.java index 850f1df24ee..1d96cd1f326 100644 --- a/jdk/src/java.base/share/classes/java/util/spi/ToolProvider.java +++ b/jdk/src/java.base/share/classes/java/util/spi/ToolProvider.java @@ -56,8 +56,8 @@ public interface ToolProvider { /** * Returns the name of this tool provider. * - * @apiNote It is recommended that the name be the same as would be used on - * the command line: for example, "javac", "jar", "jlink". + * @apiNote It is recommended that the name be the same as would be + * used on the command line: for example, "javac", "jar", "jlink". * * @return the name of this tool provider */ @@ -67,12 +67,13 @@ public interface ToolProvider { * Runs an instance of the tool, returning zero for a successful run. * Any non-zero return value indicates a tool-specific error during the * execution. + * * Two streams should be provided, for "expected" output, and for any * error messages. If it is not necessary to distinguish the output, * the same stream may be used for both. * * @apiNote The interpretation of the arguments will be specific to - * each tool. + * each tool. * * @param out a stream to which "expected" output should be written * @@ -81,12 +82,13 @@ public interface ToolProvider { * @param args the command-line arguments for the tool * * @return the result of executing the tool. - * A return value of 0 means the tool did not encounter any errors; - * any other value indicates that at least one error occurred during - * execution. + * A return value of 0 means the tool did not encounter any errors; + * any other value indicates that at least one error occurred + * during execution. * * @throws NullPointerException if any of the arguments are {@code null}, - * or if there are any {@code null} values in the {@code args} array + * or if there are any {@code null} values in the {@code args} + * array */ int run(PrintWriter out, PrintWriter err, String... args); @@ -94,16 +96,17 @@ public interface ToolProvider { * Runs an instance of the tool, returning zero for a successful run. * Any non-zero return value indicates a tool-specific error during the * execution. + * * Two streams should be provided, for "expected" output, and for any * error messages. If it is not necessary to distinguish the output, * the same stream may be used for both. * * @apiNote The interpretation of the arguments will be specific to - * each tool. + * each tool. * * @implNote This implementation wraps the {@code out} and {@code err} - * streams within {@link PrintWriter}s, and then calls - * {@link run(PrintWriter, PrintWriter, String[])}. + * streams within {@link PrintWriter}s, and then calls + * {@link #run(PrintWriter, PrintWriter, String[])}. * * @param out a stream to which "expected" output should be written * @@ -112,12 +115,13 @@ public interface ToolProvider { * @param args the command-line arguments for the tool * * @return the result of executing the tool. - * A return value of 0 means the tool did not encounter any errors; - * any other value indicates that at least one error occurred during - * execution. + * A return value of 0 means the tool did not encounter any errors; + * any other value indicates that at least one error occurred + * during execution. * * @throws NullPointerException if any of the arguments are {@code null}, - * or if there are any {@code null} values in the {@code args} array + * or if there are any {@code null} values in the {@code args} + * array */ default int run(PrintStream out, PrintStream err, String... args) { Objects.requireNonNull(out); diff --git a/jdk/src/java.base/share/classes/java/util/stream/Collectors.java b/jdk/src/java.base/share/classes/java/util/stream/Collectors.java index 018bb5fc1b6..fd7b0a477fa 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/Collectors.java +++ b/jdk/src/java.base/share/classes/java/util/stream/Collectors.java @@ -27,7 +27,6 @@ package java.util.stream; import java.util.AbstractMap; import java.util.AbstractSet; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -1720,12 +1719,12 @@ public final class Collectors { @Override public Set> entrySet() { - return new AbstractSet>() { + return new AbstractSet<>() { @Override public Iterator> iterator() { Map.Entry falseEntry = new SimpleImmutableEntry<>(false, forFalse); Map.Entry trueEntry = new SimpleImmutableEntry<>(true, forTrue); - return Arrays.asList(falseEntry, trueEntry).iterator(); + return List.of(falseEntry, trueEntry).iterator(); } @Override diff --git a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java index ca40bf2706e..cacb97978f3 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java @@ -430,22 +430,23 @@ public final class ModuleBootstrap { // the key is $MODULE String mn = e.getKey(); Optional om = bootLayer.findModule(mn); - if (!om.isPresent()) - fail("Unknown module: " + mn); + if (!om.isPresent()) { + warn("Unknown module: " + mn); + continue; + } Module m = om.get(); // the value is the set of other modules (by name) for (String name : e.getValue()) { - - Module other; if (ALL_UNNAMED.equals(name)) { Modules.addReadsAllUnnamed(m); } else { om = bootLayer.findModule(name); - if (!om.isPresent()) - fail("Unknown module: " + name); - other = om.get(); - Modules.addReads(m, other); + if (om.isPresent()) { + Modules.addReads(m, om.get()); + } else { + warn("Unknown module: " + name); + } } } @@ -472,14 +473,24 @@ public final class ModuleBootstrap { String mn = s[0]; String pn = s[1]; + if (mn.isEmpty() || pn.isEmpty()) + fail("Module and package name must be specified:" + key); // The exporting module is in the boot layer Module m; Optional om = bootLayer.findModule(mn); - if (!om.isPresent()) - fail("Unknown module: " + mn); + if (!om.isPresent()) { + warn("Unknown module: " + mn); + continue; + } + m = om.get(); + if (!m.getDescriptor().packages().contains(pn)) { + warn("package " + pn + " not in " + mn); + continue; + } + // the value is the set of modules to export to (by name) for (String name : e.getValue()) { boolean allUnnamed = false; @@ -491,10 +502,10 @@ public final class ModuleBootstrap { if (om.isPresent()) { other = om.get(); } else { - fail("Unknown module: " + name); + warn("Unknown module: " + name); + continue; } } - if (allUnnamed) { Modules.addExportsToAllUnnamed(m, pn); } else { @@ -534,13 +545,7 @@ public final class ModuleBootstrap { if (rhs.isEmpty()) fail("Unable to parse: " + value); - - // value is (,)* - if (map.containsKey(key)) - fail(key + " specified more than once"); - - Set values = new HashSet<>(); - map.put(key, values); + Set values = map.computeIfAbsent(key, k -> new HashSet<>()); for (String s : rhs.split(",")) { if (s.length() > 0) values.add(s); } @@ -566,6 +571,10 @@ public final class ModuleBootstrap { throw new RuntimeException(m); } + static void warn(String m) { + System.err.println("WARNING: " + m); + } + static class PerfCounters { static PerfCounter systemModulesTime diff --git a/jdk/src/java.base/share/classes/module-info.java b/jdk/src/java.base/share/classes/module-info.java index 4cb223881bc..e376a502579 100644 --- a/jdk/src/java.base/share/classes/module-info.java +++ b/jdk/src/java.base/share/classes/module-info.java @@ -154,7 +154,6 @@ module java.base { exports jdk.internal.module to java.instrument, java.management, - jdk.dynalink, jdk.jartool, jdk.jlink; exports jdk.internal.misc to diff --git a/jdk/src/java.base/share/classes/sun/nio/cs/HKSCS.java b/jdk/src/java.base/share/classes/sun/nio/cs/HKSCS.java index ed920e74ade..1b166447b78 100644 --- a/jdk/src/java.base/share/classes/sun/nio/cs/HKSCS.java +++ b/jdk/src/java.base/share/classes/sun/nio/cs/HKSCS.java @@ -432,6 +432,8 @@ public class HKSCS { continue; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); + if (c == UNMAPPABLE_DECODING) + continue; int hi = c >> 8; if (c2b[hi] == C2B_UNMAPPABLE) { c2b[hi] = new char[0x100]; diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/EllipticCurvesExtension.java b/jdk/src/java.base/share/classes/sun/security/ssl/EllipticCurvesExtension.java index 632d0da18f1..d4f2848c973 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/EllipticCurvesExtension.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/EllipticCurvesExtension.java @@ -282,7 +282,7 @@ final class EllipticCurvesExtension extends HelloExtension { private static int getPreferredCurve(int[] curves, AlgorithmConstraints constraints) { for (int curveId : curves) { - if (constraints.permits( + if (isSupported(curveId) && constraints.permits( EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), "EC", idToParams.get(curveId))) { return curveId; diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java index b3740cfcd86..4717fbba178 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java @@ -49,6 +49,7 @@ import sun.security.internal.spec.TlsPrfParameterSpec; import sun.security.ssl.CipherSuite.*; import static sun.security.ssl.CipherSuite.PRF.*; import sun.security.util.KeyUtil; +import sun.security.util.MessageDigestSpi2; import sun.security.provider.certpath.OCSPResponse; /** @@ -2124,63 +2125,14 @@ static final class CertificateVerify extends HandshakeMessage { md.update(temp); } - private static final Class delegate; - private static final Field spiField; - - static { - try { - delegate = Class.forName("java.security.MessageDigest$Delegate"); - spiField = delegate.getDeclaredField("digestSpi"); - } catch (Exception e) { - throw new RuntimeException("Reflection failed", e); - } - makeAccessible(spiField); - } - - private static void makeAccessible(final AccessibleObject o) { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Object run() { - o.setAccessible(true); - return null; - } - }); - } - - // ConcurrentHashMap does not allow null values, use this marker object - private static final Object NULL_OBJECT = new Object(); - - // cache Method objects per Spi class - // Note that this will prevent the Spi classes from being GC'd. We assume - // that is not a problem. - private static final Map,Object> methodCache = - new ConcurrentHashMap<>(); - private static void digestKey(MessageDigest md, SecretKey key) { try { - // Verify that md is implemented via MessageDigestSpi, not - // via JDK 1.1 style MessageDigest subclassing. - if (md.getClass() != delegate) { - throw new Exception("Digest is not a MessageDigestSpi"); - } - MessageDigestSpi spi = (MessageDigestSpi)spiField.get(md); - Class clazz = spi.getClass(); - Object r = methodCache.get(clazz); - if (r == null) { - try { - r = clazz.getDeclaredMethod("implUpdate", SecretKey.class); - makeAccessible((Method)r); - } catch (NoSuchMethodException e) { - r = NULL_OBJECT; - } - methodCache.put(clazz, r); - } - if (r == NULL_OBJECT) { + if (md instanceof MessageDigestSpi2) { + ((MessageDigestSpi2)md).engineUpdate(key); + } else { throw new Exception( "Digest does not support implUpdate(SecretKey)"); } - Method update = (Method)r; - update.invoke(spi, key); } catch (Exception e) { throw new RuntimeException( "Could not obtain encoded key and " diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java index c68e7431053..a8870960ca6 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java @@ -1172,11 +1172,18 @@ final class ServerHandshaker extends Handshaker { if (trySetCipherSuite(suite) == false) { continue; } + + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Standard ciphersuite chosen: " + suite); + } return; } for (CipherSuite suite : legacySuites) { if (trySetCipherSuite(suite)) { + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Legacy ciphersuite chosen: " + suite); + } return; } } diff --git a/jdk/src/java.base/share/classes/sun/security/util/MessageDigestSpi2.java b/jdk/src/java.base/share/classes/sun/security/util/MessageDigestSpi2.java new file mode 100644 index 00000000000..4fbf285a8a2 --- /dev/null +++ b/jdk/src/java.base/share/classes/sun/security/util/MessageDigestSpi2.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.util; + +import java.security.InvalidKeyException; +import javax.crypto.SecretKey; + +/** + * Special interface for additional MessageDigestSpi method(s). + */ +public interface MessageDigestSpi2 { + + /** + * Updates the digest using the specified key. + * This is used for SSL 3.0 only, we may deprecate and remove the support + * of this in the future + * + * @param key the key whose value is to be digested. + */ + void engineUpdate(SecretKey key) throws InvalidKeyException; +} diff --git a/jdk/src/java.base/share/lib/security/default.policy b/jdk/src/java.base/share/lib/security/default.policy index f57e67fb482..37b82049dfc 100644 --- a/jdk/src/java.base/share/lib/security/default.policy +++ b/jdk/src/java.base/share/lib/security/default.policy @@ -91,7 +91,6 @@ grant codeBase "jrt:/java.xml.ws" { }; grant codeBase "jrt:/jdk.charsets" { - permission java.io.FilePermission "${java.home}/-", "read"; permission java.util.PropertyPermission "os.name", "read"; permission java.util.PropertyPermission "sun.nio.cs.map", "read"; permission java.lang.RuntimePermission "charsetProvider"; diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java index de822922b36..37dd499e727 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Base64.java @@ -376,14 +376,14 @@ public class Base64 { return null; } - int lengthDataBits = binaryData.length * EIGHTBIT; - if (lengthDataBits == 0) { + long lengthDataBits = ((long) binaryData.length) * ((long) EIGHTBIT); + if (lengthDataBits == 0L) { return ""; } - int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; - int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP; - int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets; + long fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP; + int numberTriplets = (int) (lengthDataBits / TWENTYFOURBITGROUP); + int numberQuartet = fewerThan24bits != 0L ? numberTriplets + 1 : numberTriplets; int quartesPerLine = length / 4; int numberLines = (numberQuartet - 1) / quartesPerLine; char encodedData[] = null; diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Digest.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Digest.java index 2dc66d2368b..c82e44b219f 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Digest.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11Digest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,8 @@ import javax.crypto.SecretKey; import sun.nio.ch.DirectBuffer; +import sun.security.util.MessageDigestSpi2; + import sun.security.pkcs11.wrapper.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; @@ -49,7 +51,8 @@ import static sun.security.pkcs11.wrapper.PKCS11Constants.*; * @author Andreas Sterbenz * @since 1.5 */ -final class P11Digest extends MessageDigestSpi implements Cloneable { +final class P11Digest extends MessageDigestSpi implements Cloneable, + MessageDigestSpi2 { /* fields initialized, no session acquired */ private final static int S_BLANK = 1; @@ -233,10 +236,11 @@ final class P11Digest extends MessageDigestSpi implements Cloneable { } // Called by SunJSSE via reflection during the SSL 3.0 handshake if - // the master secret is sensitive. We may want to consider making this - // method public in a future release. - protected void implUpdate(SecretKey key) throws InvalidKeyException { - + // the master secret is sensitive. + // Note: Change to protected after this method is moved from + // sun.security.util.MessageSpi2 interface to + // java.security.MessageDigestSpi class + public void engineUpdate(SecretKey key) throws InvalidKeyException { // SunJSSE calls this method only if the key does not have a RAW // encoding, i.e. if it is sensitive. Therefore, no point in calling // SecretKeyFactory to try to convert it. Just verify it ourselves. diff --git a/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java index 84341e1e181..999b0f7bd91 100644 --- a/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java +++ b/jdk/src/jdk.internal.le/share/classes/jdk/internal/jline/console/ConsoleReader.java @@ -2339,7 +2339,7 @@ public class ConsoleReader Stack pushBackChar = new Stack(); - if (terminal.isAnsiSupported()) { + if (terminal.isAnsiSupported() && System.console() != null) { //detect the prompt length by reading the cursor position from the terminal //the real prompt length could differ from the simple prompt length due to //use of escape sequences: diff --git a/jdk/src/jdk.jartool/share/classes/module-info.java b/jdk/src/jdk.jartool/share/classes/module-info.java index cbf703263d4..536ca81b684 100644 --- a/jdk/src/jdk.jartool/share/classes/module-info.java +++ b/jdk/src/jdk.jartool/share/classes/module-info.java @@ -26,5 +26,7 @@ module jdk.jartool { exports com.sun.jarsigner; exports jdk.security.jarsigner; + + provides java.util.spi.ToolProvider with sun.tools.jar.JarToolProvider; } diff --git a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java index 165a424d9ca..17b4c1725cc 100644 --- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java +++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/GNUStyleOptions.java @@ -27,6 +27,7 @@ package sun.tools.jar; import java.io.File; import java.io.PrintStream; +import java.io.PrintWriter; import java.lang.module.ModuleFinder; import java.lang.module.ModuleDescriptor.Version; import java.nio.file.Path; @@ -253,7 +254,8 @@ class GNUStyleOptions { // process options for (; count < args.length; count++) { - if (args[count].charAt(0) != '-' || args[count].equals("-C")) + if (args[count].charAt(0) != '-' || args[count].equals("-C") + || args[count].equals("--release")) break; String name = args[count]; @@ -289,7 +291,7 @@ class GNUStyleOptions { throw new BadArgs("error.unrecognized.option", name).showUsage(true); } - static void printHelp(PrintStream out) { + static void printHelp(PrintWriter out) { out.format("%s%n", Main.getMsg("main.help.preopt")); for (OptionType type : OptionType.values()) { boolean typeHeadingWritten = false; @@ -312,16 +314,16 @@ class GNUStyleOptions { out.format("%n%s%n%n", Main.getMsg("main.help.postopt")); } - static void printCompatHelp(PrintStream out) { + static void printCompatHelp(PrintWriter out) { out.format("%s%n", Main.getMsg("usage.compat")); } - static void printUsageSummary(PrintStream out) { + static void printUsageSummary(PrintWriter out) { out.format("%s%n", Main.getMsg("main.usage.summary")); out.format("%s%n", Main.getMsg("main.usage.summary.try")); } - static void printVersion(PrintStream out) { + static void printVersion(PrintWriter out) { out.format("%s %s%n", "jar", System.getProperty("java.version")); } } diff --git a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/JarToolProvider.java b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/JarToolProvider.java new file mode 100644 index 00000000000..959db36a2f1 --- /dev/null +++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/JarToolProvider.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.tools.jar; + +import java.io.PrintWriter; +import java.util.spi.ToolProvider; + +public class JarToolProvider implements ToolProvider { + public String name() { + return "jar"; + } + + public int run(PrintWriter out, PrintWriter err, String... args) { + boolean ok = new Main(out, err, name()).run(args); + return ok ? 0 : 1; + } +} diff --git a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java index 41ccfe9f774..6aa65550140 100644 --- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java +++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java @@ -76,7 +76,7 @@ import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; public class Main { String program; - PrintStream out, err; + PrintWriter out, err; String fname, mname, ename; String zname = ""; String rootjar = null; @@ -189,9 +189,9 @@ class Main { USAGE_SUMMARY(GNUStyleOptions::printUsageSummary), VERSION(GNUStyleOptions::printVersion); - private Consumer printFunction; - Info(Consumer f) { this.printFunction = f; } - void print(PrintStream out) { printFunction.accept(out); } + private Consumer printFunction; + Info(Consumer f) { this.printFunction = f; } + void print(PrintWriter out) { printFunction.accept(out); } }; Info info; @@ -252,6 +252,12 @@ class Main { } public Main(PrintStream out, PrintStream err, String program) { + this.out = new PrintWriter(out, true); + this.err = new PrintWriter(err, true); + this.program = program; + } + + public Main(PrintWriter out, PrintWriter err, String program) { this.out = out; this.err = err; this.program = program; diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java index dfecf9e0c3a..8fa165c1940 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java @@ -153,7 +153,7 @@ public class JlinkTask { = taskHelper.newOptionsHelper(JlinkTask.class, recognizedOptions); private PrintWriter log; - void setLog(PrintWriter out) { + void setLog(PrintWriter out, PrintWriter err) { log = out; taskHelper.setLog(log); } @@ -182,7 +182,8 @@ public class JlinkTask { int run(String[] args) { if (log == null) { - setLog(new PrintWriter(System.out, true)); + setLog(new PrintWriter(System.out, true), + new PrintWriter(System.err, true)); } try { optionsHelper.handleOptions(this, args); diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java index 651480de253..d9f968d4d78 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/Main.java @@ -26,6 +26,7 @@ package jdk.tools.jlink.internal; import java.io.*; +import java.util.spi.ToolProvider; public class Main { public static void main(String... args) throws Exception { @@ -34,17 +35,27 @@ public class Main { System.exit(rc); } - /** * Entry point that does not call System.exit. * - * @param args command line arguments * @param out output stream + * @param err error output stream + * @param args command line arguments * @return an exit code. 0 means success, non-zero means an error occurred. */ - public static int run(String[] args, PrintWriter out) { + public static int run(PrintWriter out, PrintWriter err, String... args) { JlinkTask t = new JlinkTask(); - t.setLog(out); + t.setLog(out, err); return t.run(args); } + + public static class JlinkToolProvider implements ToolProvider { + public String name() { + return "jlink"; + } + + public int run(PrintWriter out, PrintWriter err, String... args) { + return Main.run(out, err, args); + } + } } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java index 6c23ce01bba..e37d9968800 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java @@ -32,6 +32,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; +import java.io.PrintWriter; import java.io.UncheckedIOException; import java.lang.module.Configuration; import java.lang.module.ModuleReader; @@ -136,8 +137,8 @@ public class JmodTask { private static final String MODULE_INFO = "module-info.class"; private Options options; - private PrintStream out = System.out; - void setLog(PrintStream out) { + private PrintWriter out = new PrintWriter(System.out, true); + void setLog(PrintWriter out, PrintWriter err) { this.out = out; } diff --git a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/Main.java b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/Main.java index 227f9948e65..1d069607d05 100644 --- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/Main.java +++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/Main.java @@ -26,6 +26,7 @@ package jdk.tools.jmod; import java.io.*; +import java.util.spi.ToolProvider; public class Main { public static void main(String... args) throws Exception { @@ -37,13 +38,24 @@ public class Main { /** * Entry point that does not call System.exit. * - * @param args command line arguments * @param out output stream + * @param err error output stream + * @param args command line arguments * @return an exit code. 0 means success, non-zero means an error occurred. */ - public static int run(String[] args, PrintStream out) { + public static int run(PrintWriter out, PrintWriter err, String... args) { JmodTask t = new JmodTask(); - t.setLog(out); + t.setLog(out, err); return t.run(args); } + + public static class JmodToolProvider implements ToolProvider { + public String name() { + return "jmod"; + } + + public int run(PrintWriter out, PrintWriter err, String... args) { + return Main.run(out, err, args); + } + } } diff --git a/jdk/src/jdk.jlink/share/classes/module-info.java b/jdk/src/jdk.jlink/share/classes/module-info.java index 0b1995129f2..2564412d59c 100644 --- a/jdk/src/jdk.jlink/share/classes/module-info.java +++ b/jdk/src/jdk.jlink/share/classes/module-info.java @@ -31,6 +31,9 @@ module jdk.jlink { uses jdk.tools.jlink.plugin.Plugin; + provides java.util.spi.ToolProvider with jdk.tools.jmod.Main.JmodToolProvider; + provides java.util.spi.ToolProvider with jdk.tools.jlink.internal.Main.JlinkToolProvider; + provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.FileCopierPlugin; provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.StripDebugPlugin; provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ExcludePlugin; diff --git a/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java b/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java index cdeb61b899a..139a56871b9 100644 --- a/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java +++ b/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java @@ -25,8 +25,8 @@ * @test * @library /lib/testlibrary * @modules java.base/jdk.internal.module - * jdk.jlink/jdk.tools.jmod * jdk.compiler + * jdk.jlink * @build ModuleReaderTest CompilerUtils JarUtils * @run testng ModuleReaderTest * @summary Basic tests for java.lang.module.ModuleReader @@ -48,6 +48,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.Optional; +import java.util.spi.ToolProvider; import jdk.internal.module.ConfigurableModuleFinder; import jdk.internal.module.ConfigurableModuleFinder.Phase; @@ -196,8 +197,11 @@ public class ModuleReaderTest { String cp = MODS_DIR.resolve(TEST_MODULE).toString(); String jmod = dir.resolve("m.jmod").toString(); String[] args = { "create", "--class-path", cp, jmod }; - jdk.tools.jmod.JmodTask task = new jdk.tools.jmod.JmodTask(); - assertEquals(task.run(args), 0); + ToolProvider jmodTool = ToolProvider.findFirst("jmod") + .orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); + assertEquals(jmodTool.run(System.out, System.out, args), 0); test(dir); } diff --git a/jdk/test/java/security/KeyStore/TestKeyStoreBasic.java b/jdk/test/java/security/KeyStore/TestKeyStoreBasic.java index fe18a8943a5..b96c26499c3 100644 --- a/jdk/test/java/security/KeyStore/TestKeyStoreBasic.java +++ b/jdk/test/java/security/KeyStore/TestKeyStoreBasic.java @@ -40,7 +40,7 @@ import java.util.Base64; /* * @test - * @bug 8048621 8133090 + * @bug 8048621 8133090 8167371 * @summary Test basic operations with keystores (jks, jceks, pkcs12) * @author Yu-Ching Valerie PENG */ @@ -116,6 +116,8 @@ public class TestKeyStoreBasic { }; private static final String ALIAS_HEAD = "test"; + private static final String CRYPTO_ALG = "PBEWithHmacSHA256AndAES_128"; + public static void main(String args[]) throws Exception { TestKeyStoreBasic jstest = new TestKeyStoreBasic(); jstest.run(); @@ -125,7 +127,7 @@ public class TestKeyStoreBasic { for (String provider : PROVIDERS) { try { runTest(provider); - System.out.println("Test with provider " + provider + "passed"); + System.out.println("Test with provider " + provider + " passed"); } catch (java.security.KeyStoreException e) { if (provider.equals("SunPKCS11-Solaris")) { System.out.println("KeyStoreException is expected: " @@ -236,6 +238,44 @@ public class TestKeyStoreBasic { // compare the creation date of the 2 key stores for all aliases compareCreationDate(ks, ks2, numEntries); + // check setEntry/getEntry with a password protection algorithm + if ("PKCS12".equalsIgnoreCase(ks.getType())) { + System.out.println( + "Skipping the setEntry/getEntry check for PKCS12 keystore..."); + return; + } + String alias = ALIAS_HEAD + ALIAS_HEAD; + KeyStore.PasswordProtection pw = + new KeyStore.PasswordProtection(PASSWD2, CRYPTO_ALG, null); + KeyStore.PrivateKeyEntry entry = + new KeyStore.PrivateKeyEntry(privateKey, new Certificate[]{ cert }); + checkSetEntry(ks, alias, pw, entry); + ks.setEntry(alias, entry, new KeyStore.PasswordProtection(PASSWD2)); + checkGetEntry(ks, alias, pw); + } + + // check setEntry with a password protection algorithm + private void checkSetEntry(KeyStore ks, String alias, + KeyStore.PasswordProtection pw, KeyStore.Entry entry) throws Exception { + try { + ks.setEntry(alias, entry, pw); + throw new Exception( + "ERROR: expected KeyStore.setEntry to throw an exception"); + } catch (KeyStoreException e) { + // ignore the expected exception + } + } + + // check getEntry with a password protection algorithm + private void checkGetEntry(KeyStore ks, String alias, + KeyStore.PasswordProtection pw) throws Exception { + try { + ks.getEntry(alias, pw); + throw new Exception( + "ERROR: expected KeyStore.getEntry to throw an exception"); + } catch (KeyStoreException e) { + // ignore the expected exception + } } // check key store type diff --git a/jdk/test/java/util/concurrent/tck/AtomicBoolean9Test.java b/jdk/test/java/util/concurrent/tck/AtomicBoolean9Test.java index 7211dca7ebd..fd27716c155 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicBoolean9Test.java +++ b/jdk/test/java/util/concurrent/tck/AtomicBoolean9Test.java @@ -161,6 +161,19 @@ public class AtomicBoolean9Test extends JSR166TestCase { assertEquals(true, ai.get()); } + /** + * repeated weakCompareAndSetPlain succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSetPlain() { + AtomicBoolean ai = new AtomicBoolean(true); + do {} while (!ai.weakCompareAndSetPlain(true, false)); + do {} while (!ai.weakCompareAndSetPlain(false, false)); + assertFalse(ai.get()); + do {} while (!ai.weakCompareAndSetPlain(false, true)); + assertTrue(ai.get()); + } + /** * repeated weakCompareAndSetVolatile succeeds in changing value when equal * to expected diff --git a/jdk/test/java/util/concurrent/tck/AtomicInteger9Test.java b/jdk/test/java/util/concurrent/tck/AtomicInteger9Test.java index 7a0ed578f9a..cd18c2375ae 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicInteger9Test.java +++ b/jdk/test/java/util/concurrent/tck/AtomicInteger9Test.java @@ -161,6 +161,19 @@ public class AtomicInteger9Test extends JSR166TestCase { assertEquals(7, ai.get()); } + /** + * repeated weakCompareAndSetPlain succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSetPlain() { + AtomicInteger ai = new AtomicInteger(1); + do {} while (!ai.weakCompareAndSetPlain(1, 2)); + do {} while (!ai.weakCompareAndSetPlain(2, -4)); + assertEquals(-4, ai.get()); + do {} while (!ai.weakCompareAndSetPlain(-4, 7)); + assertEquals(7, ai.get()); + } + /** * repeated weakCompareAndSetVolatile succeeds in changing value when equal * to expected diff --git a/jdk/test/java/util/concurrent/tck/AtomicIntegerArray9Test.java b/jdk/test/java/util/concurrent/tck/AtomicIntegerArray9Test.java index b7b20bdf6b0..eb25146561e 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicIntegerArray9Test.java +++ b/jdk/test/java/util/concurrent/tck/AtomicIntegerArray9Test.java @@ -62,6 +62,7 @@ public class AtomicIntegerArray9Test extends JSR166TestCase { () -> aa.compareAndExchange(j, 1, 2), () -> aa.compareAndExchangeAcquire(j, 1, 2), () -> aa.compareAndExchangeRelease(j, 1, 2), + () -> aa.weakCompareAndSetPlain(j, 1, 2), () -> aa.weakCompareAndSetVolatile(j, 1, 2), () -> aa.weakCompareAndSetAcquire(j, 1, 2), () -> aa.weakCompareAndSetRelease(j, 1, 2), @@ -215,6 +216,22 @@ public class AtomicIntegerArray9Test extends JSR166TestCase { } } + /** + * repeated weakCompareAndSetPlain succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSetPlain() { + AtomicIntegerArray aa = new AtomicIntegerArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + do {} while (!aa.weakCompareAndSetPlain(i, 1, 2)); + do {} while (!aa.weakCompareAndSetPlain(i, 2, -4)); + assertEquals(-4, aa.get(i)); + do {} while (!aa.weakCompareAndSetPlain(i, -4, 7)); + assertEquals(7, aa.get(i)); + } + } + /** * repeated weakCompareAndSetVolatile succeeds in changing value when equal * to expected diff --git a/jdk/test/java/util/concurrent/tck/AtomicLong9Test.java b/jdk/test/java/util/concurrent/tck/AtomicLong9Test.java index c11561690b8..c83f1326c8e 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicLong9Test.java +++ b/jdk/test/java/util/concurrent/tck/AtomicLong9Test.java @@ -161,6 +161,19 @@ public class AtomicLong9Test extends JSR166TestCase { assertEquals(7, ai.get()); } + /** + * repeated weakCompareAndSetPlain succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSetPlain() { + AtomicLong ai = new AtomicLong(1); + do {} while (!ai.weakCompareAndSetPlain(1, 2)); + do {} while (!ai.weakCompareAndSetPlain(2, -4)); + assertEquals(-4, ai.get()); + do {} while (!ai.weakCompareAndSetPlain(-4, 7)); + assertEquals(7, ai.get()); + } + /** * repeated weakCompareAndSetVolatile succeeds in changing value when equal * to expected diff --git a/jdk/test/java/util/concurrent/tck/AtomicLongArray9Test.java b/jdk/test/java/util/concurrent/tck/AtomicLongArray9Test.java index 2011c789b91..6c699d4e38a 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicLongArray9Test.java +++ b/jdk/test/java/util/concurrent/tck/AtomicLongArray9Test.java @@ -61,6 +61,7 @@ public class AtomicLongArray9Test extends JSR166TestCase { () -> aa.compareAndExchange(j, 1, 2), () -> aa.compareAndExchangeAcquire(j, 1, 2), () -> aa.compareAndExchangeRelease(j, 1, 2), + () -> aa.weakCompareAndSetPlain(j, 1, 2), () -> aa.weakCompareAndSetVolatile(j, 1, 2), () -> aa.weakCompareAndSetAcquire(j, 1, 2), () -> aa.weakCompareAndSetRelease(j, 1, 2), @@ -214,6 +215,22 @@ public class AtomicLongArray9Test extends JSR166TestCase { } } + /** + * repeated weakCompareAndSetPlain succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSetPlain() { + AtomicLongArray aa = new AtomicLongArray(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, 1); + do {} while (!aa.weakCompareAndSetPlain(i, 1, 2)); + do {} while (!aa.weakCompareAndSetPlain(i, 2, -4)); + assertEquals(-4, aa.get(i)); + do {} while (!aa.weakCompareAndSetPlain(i, -4, 7)); + assertEquals(7, aa.get(i)); + } + } + /** * repeated weakCompareAndSetVolatile succeeds in changing value when equal * to expected diff --git a/jdk/test/java/util/concurrent/tck/AtomicReference9Test.java b/jdk/test/java/util/concurrent/tck/AtomicReference9Test.java index f1d974908c7..f864209b952 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicReference9Test.java +++ b/jdk/test/java/util/concurrent/tck/AtomicReference9Test.java @@ -161,6 +161,19 @@ public class AtomicReference9Test extends JSR166TestCase { assertEquals(seven, ai.get()); } + /** + * repeated weakCompareAndSetPlain succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSetPlain() { + AtomicReference ai = new AtomicReference<>(one); + do {} while (!ai.weakCompareAndSetPlain(one, two)); + do {} while (!ai.weakCompareAndSetPlain(two, m4)); + assertEquals(m4, ai.get()); + do {} while (!ai.weakCompareAndSetPlain(m4, seven)); + assertEquals(seven, ai.get()); + } + /** * repeated weakCompareAndSetVolatile succeeds in changing value when equal * to expected diff --git a/jdk/test/java/util/concurrent/tck/AtomicReferenceArray9Test.java b/jdk/test/java/util/concurrent/tck/AtomicReferenceArray9Test.java index 44bcdbe281f..f67c3cdd166 100644 --- a/jdk/test/java/util/concurrent/tck/AtomicReferenceArray9Test.java +++ b/jdk/test/java/util/concurrent/tck/AtomicReferenceArray9Test.java @@ -61,6 +61,7 @@ public class AtomicReferenceArray9Test extends JSR166TestCase { () -> aa.compareAndExchange(j, null, null), () -> aa.compareAndExchangeAcquire(j, null, null), () -> aa.compareAndExchangeRelease(j, null, null), + () -> aa.weakCompareAndSetPlain(j, null, null), () -> aa.weakCompareAndSetVolatile(j, null, null), () -> aa.weakCompareAndSetAcquire(j, null, null), () -> aa.weakCompareAndSetRelease(j, null, null), @@ -214,6 +215,22 @@ public class AtomicReferenceArray9Test extends JSR166TestCase { } } + /** + * repeated weakCompareAndSetPlain succeeds in changing value when equal + * to expected + */ + public void testWeakCompareAndSetPlain() { + AtomicReferenceArray aa = new AtomicReferenceArray<>(SIZE); + for (int i = 0; i < SIZE; i++) { + aa.set(i, one); + do {} while (!aa.weakCompareAndSetPlain(i, one, two)); + do {} while (!aa.weakCompareAndSetPlain(i, two, m4)); + assertEquals(m4, aa.get(i)); + do {} while (!aa.weakCompareAndSetPlain(i, m4, seven)); + assertEquals(seven, aa.get(i)); + } + } + /** * repeated weakCompareAndSetVolatile succeeds in changing value when equal * to expected diff --git a/jdk/test/jdk/internal/util/jar/TestVersionedStream.java b/jdk/test/jdk/internal/util/jar/TestVersionedStream.java index 12e45f03b77..5dbef938752 100644 --- a/jdk/test/jdk/internal/util/jar/TestVersionedStream.java +++ b/jdk/test/jdk/internal/util/jar/TestVersionedStream.java @@ -25,13 +25,14 @@ * @test * @bug 8163798 * @summary basic tests for multi-release jar versioned streams + * @library /lib/testlibrary * @modules jdk.jartool/sun.tools.jar java.base/jdk.internal.util.jar + * @build jdk.testlibrary.FileUtils * @run testng TestVersionedStream */ import org.testng.Assert; import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -40,29 +41,31 @@ import java.io.IOException; import java.io.InputStream; import java.io.UncheckedIOException; import java.net.URI; -import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.zip.ZipFile; -public class TestVersionedStream { - private String userdir; +import jdk.testlibrary.FileUtils; - @BeforeClass - public void initialize() { - userdir = System.getProperty("user.dir", "."); +public class TestVersionedStream { + private final Path userdir; + private final Set unversionedEntryNames; + + public TestVersionedStream() throws IOException { + userdir = Paths.get(System.getProperty("user.dir", ".")); // These are not real class files even though they end with .class. // They are resource files so jar tool validation won't reject them. @@ -70,91 +73,103 @@ public class TestVersionedStream { // could be in a concealed package if this was a modular multi-release // jar. createFiles( + "base/p/Bar.class", "base/p/Foo.class", "base/p/Main.class", "v9/p/Foo.class", "v10/p/Foo.class", "v10/q/Bar.class", + "v11/p/Bar.class", "v11/p/Foo.class" ); - jar("cf mmr.jar -C base . --release 9 -C v9 . --release 10 -C v10 . --release 11 -C v11 ."); + jar("cf mmr.jar -C base . --release 9 -C v9 . " + + "--release 10 -C v10 . --release 11 -C v11 ."); System.out.println("Contents of mmr.jar\n======="); - jar("tf mmr.jar"); + + try(JarFile jf = new JarFile("mmr.jar")) { + unversionedEntryNames = jf.stream() + .map(je -> je.getName()) + .peek(System.out::println) + .map(nm -> nm.startsWith("META-INF/versions/") + ? nm.replaceFirst("META-INF/versions/\\d+/", "") + : nm) + .collect(Collectors.toCollection(LinkedHashSet::new)); + } + System.out.println("======="); } @AfterClass public void close() throws IOException { - Path root = Paths.get(userdir); - Files.walkFileTree(root, new SimpleFileVisitor<>() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - if (!dir.equals(root)) { - Files.delete(dir); - } - return FileVisitResult.CONTINUE; - } - }); + Files.walk(userdir, 1) + .filter(p -> !p.equals(userdir)) + .forEach(p -> { + try { + if (Files.isDirectory(p)) { + FileUtils.deleteFileTreeWithRetry(p); + } else { + FileUtils.deleteFileIfExistsWithRetry(p); + } + } catch (IOException x) { + throw new UncheckedIOException(x); + } + }); } @DataProvider public Object[][] data() { - List p = List.of( - "META-INF/", - "META-INF/MANIFEST.MF", - "p/", - "p/Foo.class", - "p/Main.class" - ); - List q = List.of( - "META-INF/", - "META-INF/MANIFEST.MF", - "p/", - "p/Foo.class", - "p/Main.class", - "q/", - "q/Bar.class" - ); - Runtime.Version rt = JarFile.runtimeVersion(); return new Object[][] { - {Runtime.Version.parse("8"), p}, - {Runtime.Version.parse("9"), p}, - {Runtime.Version.parse("10"), q}, - {Runtime.Version.parse("11"), q}, - {JarFile.baseVersion(), p}, - {rt, rt.major() > 9 ? q : p} + {Runtime.Version.parse("8")}, + {Runtime.Version.parse("9")}, + {Runtime.Version.parse("10")}, + {Runtime.Version.parse("11")}, + {JarFile.baseVersion()}, + {JarFile.runtimeVersion()} }; } @Test(dataProvider="data") - public void test(Runtime.Version version, List names) throws Exception { + public void test(Runtime.Version version) throws Exception { try (JarFile jf = new JarFile(new File("mmr.jar"), false, ZipFile.OPEN_READ, version); - Stream jes = jdk.internal.util.jar.VersionedStream.stream(jf)) + Stream jes = jdk.internal.util.jar.VersionedStream.stream(jf)) { Assert.assertNotNull(jes); - List entries = jes.collect(Collectors.toList()); + // put versioned entries in list so we can reuse them + List versionedEntries = jes.collect(Collectors.toList()); - // verify the correct order - List enames = entries.stream() - .map(je -> je.getName()) - .collect(Collectors.toList()); - Assert.assertEquals(enames, names); + Assert.assertTrue(versionedEntries.size() > 0); + + // also keep the names + List versionedNames = new ArrayList<>(versionedEntries.size()); + + // verify the correct order while building enames + Iterator allIt = unversionedEntryNames.iterator(); + Iterator verIt = versionedEntries.iterator(); + boolean match = false; + + while (verIt.hasNext()) { + match = false; + if (!allIt.hasNext()) break; + String name = verIt.next().getName(); + versionedNames.add(name); + while (allIt.hasNext()) { + if (name.equals(allIt.next())) { + match = true; + break; + } + } + } + if (!match) { + Assert.fail("versioned entries not in same order as unversioned entries"); + } // verify the contents Map contents = new HashMap<>(); + contents.put("p/Bar.class", "base/p/Bar.class\n"); contents.put("p/Main.class", "base/p/Main.class\n"); - if (version.major() > 9) { - contents.put("q/Bar.class", "v10/q/Bar.class\n"); - } switch (version.major()) { case 8: contents.put("p/Foo.class", "base/p/Foo.class\n"); @@ -164,9 +179,12 @@ public class TestVersionedStream { break; case 10: contents.put("p/Foo.class", "v10/p/Foo.class\n"); + contents.put("q/Bar.class", "v10/q/Bar.class\n"); break; case 11: + contents.put("p/Bar.class", "v11/p/Bar.class\n"); contents.put("p/Foo.class", "v11/p/Foo.class\n"); + contents.put("q/Bar.class", "v10/q/Bar.class\n"); break; default: Assert.fail("Test out of date, please add more cases"); @@ -174,9 +192,9 @@ public class TestVersionedStream { contents.entrySet().stream().forEach(e -> { String name = e.getKey(); - int i = enames.indexOf(name); + int i = versionedNames.indexOf(name); Assert.assertTrue(i != -1, name + " not in enames"); - JarEntry je = entries.get(i); + JarEntry je = versionedEntries.get(i); try (InputStream is = jf.getInputStream(je)) { String s = new String(is.readAllBytes()); Assert.assertTrue(s.endsWith(e.getValue()), s); @@ -210,5 +228,4 @@ public class TestVersionedStream { new sun.tools.jar.Main(System.out, System.err, "jar") .run(args.split(" +")); } - } diff --git a/jdk/test/sun/nio/cs/TestHKSCS.java b/jdk/test/sun/nio/cs/TestHKSCS.java new file mode 100644 index 00000000000..0a7f4559d32 --- /dev/null +++ b/jdk/test/sun/nio/cs/TestHKSCS.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8166258 + * @summary Some corner cases for hkscs charsets + * @modules jdk.charsets + * @run main TestHKSCS + */ + +import java.util.Arrays; + +public class TestHKSCS { + public static void main(String args[]) throws Exception { + String[] charsets = { "x-MS950-HKSCS-XP", + "x-MS950-HKSCS", + "Big5-HKSCS", + "x-Big5-HKSCS-2001" + }; + String s = "\ufffd\ud87f\udffd"; + byte[] bytes = new byte[] { 0x3f, 0x3f }; + for (String cs : charsets) { + if (!Arrays.equals(bytes, s.getBytes(cs))) { + throw new RuntimeException(cs + " failed to decode u+fffd"); + } + } + } +} diff --git a/jdk/test/sun/security/pkcs11/PKCS11Test.java b/jdk/test/sun/security/pkcs11/PKCS11Test.java index 3752baba8da..59c284d5efa 100644 --- a/jdk/test/sun/security/pkcs11/PKCS11Test.java +++ b/jdk/test/sun/security/pkcs11/PKCS11Test.java @@ -299,11 +299,12 @@ public abstract class PKCS11Test { + props.getProperty("os.arch") + "-" + props.getProperty("sun.arch.data.model"); String[] nssLibDirs = osMap.get(osid); if (nssLibDirs == null) { - System.out.println("Unsupported OS, skipping: " + osid); + System.out.println("Warning: unsupported OS: " + osid + + ", please initialize NSS librarys location firstly, skipping test"); return null; } if (nssLibDirs.length == 0) { - System.out.println("NSS not supported on this platform, skipping test"); + System.out.println("Warning: NSS not supported on this platform, skipping test"); return null; } String nssLibDir = null; @@ -315,6 +316,10 @@ public abstract class PKCS11Test { break; } } + if (nssLibDir == null) { + System.out.println("Warning: can't find NSS librarys on this machine, skipping test"); + return null; + } return nssLibDir; } @@ -624,6 +629,11 @@ public abstract class PKCS11Test { PKCS11_BASE + "/nss/lib/windows-amd64/".replace('/', SEP)}); osMap.put("MacOSX-x86_64-64", new String[]{ PKCS11_BASE + "/nss/lib/macosx-x86_64/"}); + osMap.put("Linux-arm-32", new String[]{ + "/usr/lib/arm-linux-gnueabi/nss/", + "/usr/lib/arm-linux-gnueabihf/nss/"}); + osMap.put("Linux-aarch64-64", new String[]{ + "/usr/lib/aarch64-linux-gnu/nss/"}); } private final static char[] hexDigits = "0123456789abcdef".toCharArray(); diff --git a/jdk/test/sun/tools/jrunscript/jrunscript-DTest.sh b/jdk/test/sun/tools/jrunscript/jrunscript-DTest.sh index b2102ef6a62..4e99fcd8adb 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscript-DTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscript-DTest.sh @@ -33,7 +33,7 @@ . ${TESTSRC-.}/common.sh setup -${JAVA} -cp ${TESTCLASSES} CheckEngine +${JAVA} ${TESTVMOPTS} ${TESTJAVAOPTS} -cp ${TESTCLASSES} CheckEngine if [ $? -eq 2 ]; then echo "No js engine found and engine not required; test vacuously passes." exit 0 diff --git a/jdk/test/sun/tools/jrunscript/jrunscript-argsTest.sh b/jdk/test/sun/tools/jrunscript/jrunscript-argsTest.sh index b104e965ddf..ae36204249b 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscript-argsTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscript-argsTest.sh @@ -33,7 +33,7 @@ . ${TESTSRC-.}/common.sh setup -${JAVA} -cp ${TESTCLASSES} CheckEngine +${JAVA} ${TESTVMOPTS} ${TESTJAVAOPTS} -cp ${TESTCLASSES} CheckEngine if [ $? -eq 2 ]; then echo "No js engine found and engine not required; test vacuously passes." exit 0 diff --git a/jdk/test/sun/tools/jrunscript/jrunscript-cpTest.sh b/jdk/test/sun/tools/jrunscript/jrunscript-cpTest.sh index 4b989ef2de1..67a8176fe9d 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscript-cpTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscript-cpTest.sh @@ -33,14 +33,14 @@ . ${TESTSRC-.}/common.sh setup -${JAVA} -cp ${TESTCLASSES} CheckEngine +${JAVA} ${TESTVMOPTS} ${TESTJAVAOPTS} -cp ${TESTCLASSES} CheckEngine if [ $? -eq 2 ]; then echo "No js engine found and engine not required; test vacuously passes." exit 0 fi rm -f Hello.class -${JAVAC} ${TESTSRC}/Hello.java -d . +${JAVAC} ${TESTTOOLVMOPTS} ${TESTJAVACOPTS} ${TESTSRC}/Hello.java -d . # we check whether classpath setting for app classes # work with jrunscript. Script should be able to diff --git a/jdk/test/sun/tools/jrunscript/jrunscript-eTest.sh b/jdk/test/sun/tools/jrunscript/jrunscript-eTest.sh index 97c62a261f9..7b3510c4af3 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscript-eTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscript-eTest.sh @@ -33,7 +33,7 @@ . ${TESTSRC-.}/common.sh setup -${JAVA} -cp ${TESTCLASSES} CheckEngine +${JAVA} ${TESTVMOPTS} ${TESTJAVAOPTS} -cp ${TESTCLASSES} CheckEngine if [ $? -eq 2 ]; then echo "No js engine found and engine not required; test vacuously passes." exit 0 diff --git a/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh b/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh index 8c402a316ea..6be1e9132c6 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscript-fTest.sh @@ -33,7 +33,7 @@ . ${TESTSRC-.}/common.sh setup -${JAVA} -cp ${TESTCLASSES} CheckEngine +${JAVA} ${TESTVMOPTS} ${TESTJAVAOPTS} -cp ${TESTCLASSES} CheckEngine if [ $? -eq 2 ]; then echo "No js engine found and engine not required; test vacuously passes." exit 0 diff --git a/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh b/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh index ab4cb16dc13..b95273c937b 100644 --- a/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh +++ b/jdk/test/sun/tools/jrunscript/jrunscriptTest.sh @@ -33,7 +33,7 @@ . ${TESTSRC-.}/common.sh setup -${JAVA} -cp ${TESTCLASSES} CheckEngine +${JAVA} ${TESTVMOPTS} ${TESTJAVAOPTS} -cp ${TESTCLASSES} CheckEngine if [ $? -eq 2 ]; then echo "No js engine found and engine not required; test vacuously passes." exit 0 diff --git a/jdk/test/tools/jar/ChangeDir.java b/jdk/test/tools/jar/ChangeDir.java index 7d3516bcba7..374b481bd77 100644 --- a/jdk/test/tools/jar/ChangeDir.java +++ b/jdk/test/tools/jar/ChangeDir.java @@ -24,7 +24,7 @@ /** * @test * @bug 4806786 8023113 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary jar -C doesn't ignore multiple // in path */ @@ -32,10 +32,15 @@ import java.io.*; import java.nio.file.*; import java.util.*; import java.util.jar.*; +import java.util.spi.ToolProvider; import java.util.stream.Stream; -import sun.tools.jar.Main; public class ChangeDir { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + private final static String jarName = "test.jar"; private final static String fileName = "hello.txt"; @@ -88,8 +93,9 @@ public class ChangeDir { argList.add(topDir.toString() + sep + "a" + sep + sep + "b"); // Note double 'sep' is intentional argList.add(fileName); - Main jarTool = new Main(System.out, System.err, "jar"); - if (!jarTool.run(argList.toArray(new String[argList.size()]))) { + int rc = JAR_TOOL.run(System.out, System.err, + argList.toArray(new String[argList.size()])); + if (rc != 0) { fail("Could not create jar file."); } diff --git a/jdk/test/tools/jar/InputFilesTest.java b/jdk/test/tools/jar/InputFilesTest.java index 7feaa533f93..ac5b3b29f94 100644 --- a/jdk/test/tools/jar/InputFilesTest.java +++ b/jdk/test/tools/jar/InputFilesTest.java @@ -29,7 +29,7 @@ * duplicates that sometimes cause exceptions and other times do not, * demonstrating identical behavior to JDK 8 jar tool. * @library /lib/testlibrary - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @build jdk.testlibrary.FileUtils * @run testng InputFilesTest */ @@ -47,12 +47,18 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; +import java.util.spi.ToolProvider; import java.util.stream.Stream; import java.util.zip.ZipException; import jdk.testlibrary.FileUtils; public class InputFilesTest { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + private final String nl = System.lineSeparator(); private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); private final PrintStream out = new PrintStream(baos); @@ -195,9 +201,9 @@ public class InputFilesTest { PrintStream err = new PrintStream(baes); PrintStream saveErr = System.err; System.setErr(err); - boolean ok = new sun.tools.jar.Main(out, err, "jar").run(cmdline.split(" +")); + int rc = JAR_TOOL.run(out, err, cmdline.split(" +")); System.setErr(saveErr); - if (!ok) { + if (rc != 0) { String s = baes.toString(); if (s.startsWith("java.util.zip.ZipException: duplicate entry: ")) { throw new ZipException(s); diff --git a/jdk/test/tools/jar/JarBackSlash.java b/jdk/test/tools/jar/JarBackSlash.java index 565606b8f3f..74c561d1fe6 100644 --- a/jdk/test/tools/jar/JarBackSlash.java +++ b/jdk/test/tools/jar/JarBackSlash.java @@ -28,7 +28,7 @@ /* * @test * @bug 7201156 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary jar tool fails to convert file separation characters for list and extract * @author Sean Chou */ @@ -43,10 +43,13 @@ import java.util.ArrayList; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; - -import sun.tools.jar.Main; +import java.util.spi.ToolProvider; public class JarBackSlash { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); // used construct an entry JarBackSlash/dir/file.txt private static String JARBACKSLASH = "JarBackSlash"; @@ -78,8 +81,8 @@ public class JarBackSlash { PipedInputStream pipedInput = new PipedInputStream(pipedOutput); PrintStream out = new PrintStream(pipedOutput); - Main jarTool = new Main(out, System.err, "jar"); - if (!jarTool.run(jarArgs)) { + int rc = JAR_TOOL.run(out, System.err, jarArgs); + if (rc != 0) { fail("Could not list jar file."); } @@ -101,8 +104,8 @@ public class JarBackSlash { PipedInputStream pipedInput = new PipedInputStream(pipedOutput); PrintStream out = new PrintStream(pipedOutput); - Main jarTool = new Main(out, System.err, "jar"); - if (!jarTool.run(jarArgs)) { + int rc = JAR_TOOL.run(out, System.err, jarArgs); + if (rc != 0) { fail("Could not list jar file."); } diff --git a/jdk/test/tools/jar/JarEntryTime.java b/jdk/test/tools/jar/JarEntryTime.java index 1985bb1ab66..80fd65fba5c 100644 --- a/jdk/test/tools/jar/JarEntryTime.java +++ b/jdk/test/tools/jar/JarEntryTime.java @@ -24,7 +24,7 @@ /** * @test * @bug 4225317 6969651 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary Check extracted files have date as per those in the .jar file */ @@ -33,9 +33,14 @@ import java.io.PrintWriter; import java.nio.file.attribute.FileTime; import java.util.Date; import java.util.TimeZone; -import sun.tools.jar.Main; +import java.util.spi.ToolProvider; public class JarEntryTime { + static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + // ZipEntry's mod date has 2 seconds precision: give extra time to // allow for e.g. rounding/truncation and networked/samba drives. @@ -114,10 +119,8 @@ public class JarEntryTime { check(fileInner.setLastModified(earlier)); // Make a jar file from that directory structure - Main jartool = new Main(System.out, System.err, "jar"); - check(jartool.run(new String[] { - "cf", - jarFile.getName(), dirOuter.getName() } )); + check(JAR_TOOL.run(System.out, System.err, + "cf", jarFile.getName(), dirOuter.getName()) == 0); check(jarFile.exists()); check(cleanup(dirInner)); @@ -142,7 +145,6 @@ public class JarEntryTime { final long start = testFile.lastModified(); // Extract and check the last modified values are the current times. - // See sun.tools.jar.Main extractJar(jarFile, true); try (PrintWriter pw = new PrintWriter(testFile)) { diff --git a/jdk/test/tools/jar/ReleaseBeforeFiles.java b/jdk/test/tools/jar/ReleaseBeforeFiles.java new file mode 100644 index 00000000000..56c27107a1b --- /dev/null +++ b/jdk/test/tools/jar/ReleaseBeforeFiles.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8167237 + * @summary test that both old style command line options and new gnu style + * command line options work with the --release option whether or + * not the --release option is preceded by a file name. + * @library /lib/testlibrary + * @modules jdk.jartool/sun.tools.jar + * @build jdk.testlibrary.FileUtils + * @run testng ReleaseBeforeFiles + */ + +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.stream.Stream; + +import jdk.testlibrary.FileUtils; + +public class ReleaseBeforeFiles { + private Runnable onCompletion; + + @BeforeMethod + public void reset() { + onCompletion = null; + } + + @AfterMethod + public void run() { + if (onCompletion != null) { + onCompletion.run(); + } + } + + @Test // passes before bug fix + public void test1() throws IOException { + mkdir("test1"); + touch("test1/testfile1"); + jar("cf test.jar --release 9 test1"); + jar("tf test.jar"); + rm("test.jar test1"); + } + + @Test // fails before bug fix + public void test2() throws IOException { + System.out.println("====="); + mkdir("test1"); + touch("test1/testfile1"); + onCompletion = () -> rm("test.jar test1"); + jar("--create --file=test.jar --release 9 test1"); + jar("tf test.jar"); + } + + @Test // passes before bug fix + public void test3() throws IOException { + System.out.println("====="); + mkdir("test1"); + touch("test1/testfile1"); + jar("-cf test.jar -C test1 ."); + jar("-uf test.jar --release 9 -C test1 ."); + jar("tf test.jar"); + rm("test.jar test1"); + } + + @Test // fails before bug fix + public void test4() throws IOException { + System.out.println("====="); + mkdir("test1"); + touch("test1/testfile1"); + onCompletion = () -> rm("test.jar test1"); + jar("--create --file=test.jar -C test1 ."); + jar("--update --file=test.jar --release 9 -C test1 ."); + jar("tf test.jar"); + } + + @Test // passes before bug fix since test2 precedes --release 9 + public void test5() throws IOException { + System.out.println("====="); + mkdir("test1 test2"); + touch("test1/testfile1 test2/testfile2"); + jar("--create --file=test.jar -C test1 ."); + jar("--update --file=test.jar test2 --release 9 -C test1 ."); + jar("tf test.jar"); + rm("test.jar test1 test2"); + } + + private Stream mkpath(String... args) { + return Arrays.stream(args).map(d -> Paths.get(".", d.split("/"))); + } + + private void mkdir(String cmdline) { + System.out.println("mkdir -p " + cmdline); + mkpath(cmdline.split(" +")).forEach(p -> { + try { + Files.createDirectories(p); + } catch (IOException x) { + throw new UncheckedIOException(x); + } + }); + } + + private void touch(String cmdline) { + System.out.println("touch " + cmdline); + mkpath(cmdline.split(" +")).forEach(p -> { + try { + Files.createFile(p); + } catch (IOException x) { + throw new UncheckedIOException(x); + } + }); + } + + private void rm(String cmdline) { + System.out.println("rm -rf " + cmdline); + mkpath(cmdline.split(" +")).forEach(p -> { + try { + if (Files.isDirectory(p)) { + FileUtils.deleteFileTreeWithRetry(p); + } else { + FileUtils.deleteFileIfExistsWithRetry(p); + } + } catch (IOException x) { + throw new UncheckedIOException(x); + } + }); + } + + private void jar(String cmdline) throws IOException { + System.out.println("jar " + cmdline); + boolean ok = new sun.tools.jar.Main(System.out, System.err, "jar") + .run(cmdline.split(" +")); + Assert.assertTrue(ok); + } +} diff --git a/jdk/test/tools/jar/UpdateJar.java b/jdk/test/tools/jar/UpdateJar.java index 524189bb841..c8e87bbc198 100644 --- a/jdk/test/tools/jar/UpdateJar.java +++ b/jdk/test/tools/jar/UpdateJar.java @@ -24,7 +24,7 @@ /** * @test * @bug 7175845 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary jar -uf should not change file permission */ @@ -32,9 +32,13 @@ import java.io.*; import java.nio.file.*; import java.nio.file.attribute.*; import java.util.Set; -import sun.tools.jar.Main; +import java.util.spi.ToolProvider; public class UpdateJar { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); private static void cleanup(String... fnames) throws Throwable { for (String fname : fnames) { @@ -55,12 +59,12 @@ public class UpdateJar { fos1.write(0); } String[] jarArgs = new String[] {"cfM0", jar, e0}; - if (!new Main(System.out, System.err, "jar").run(jarArgs)) { + if (JAR_TOOL.run(System.out, System.err, jarArgs) != 0) { fail("Could not create jar file."); } Set pm = Files.getPosixFilePermissions(Paths.get(jar)); jarArgs = new String[] {"uf", jar, e1}; - if (!new Main(System.out, System.err, "jar").run(jarArgs)) { + if (JAR_TOOL.run(System.out, System.err, jarArgs) != 0) { fail("Could not create jar file."); } equal(pm, Files.getPosixFilePermissions(Paths.get(jar))); diff --git a/jdk/test/tools/jar/UpdateManifest.java b/jdk/test/tools/jar/UpdateManifest.java index d07674cab17..31dbee5c68d 100644 --- a/jdk/test/tools/jar/UpdateManifest.java +++ b/jdk/test/tools/jar/UpdateManifest.java @@ -24,7 +24,7 @@ /** * @test * @bug 6434207 6442687 6984046 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary Ensure that jar ufm actually updates the * existing jar file's manifest with contents of the * manifest file. @@ -32,14 +32,19 @@ import java.io.*; import java.util.logging.*; +import java.util.spi.ToolProvider; import java.util.zip.*; -import sun.tools.jar.Main; public class UpdateManifest { static PrintStream out = System.out; static PrintStream err = System.err; static boolean debug = true; + static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + static final Logger JAR_LOGGER = Logger.getLogger("java.util.jar"); public static void realMain(String[] args) throws Throwable { @@ -64,17 +69,14 @@ public class UpdateManifest { // Create a jar file, specifying a Main-Class final String jarFileName = "um-existence.jar"; new File(jarFileName).delete(); // remove pre-existing first! - Main jartool = new Main(out, err, "jar"); - boolean status = jartool.run( - new String[] { "cfe", jarFileName, "Hello", existence.getPath() }); - check(status); + int status = JAR_TOOL.run(out, err, "cfe", jarFileName, + "Hello", existence.getPath()); + check(status == 0); checkManifest(jarFileName, "Hello"); // Update that jar file by changing the Main-Class - jartool = new Main(out, err, "jar"); - status = jartool.run( - new String[] { "ufe", jarFileName, "Bye" }); - check(status); + status = JAR_TOOL.run(out, err, "ufe", jarFileName, "Bye"); + check(status == 0); checkManifest(jarFileName, "Bye"); } @@ -101,11 +103,9 @@ public class UpdateManifest { // Create a jar file final String jarFileName = "um-test.jar"; new File(jarFileName).delete(); // remove pre-existing first! - Main jartool = new Main(out, err, "jar"); - boolean status = jartool.run( - new String[] {"cfm", jarFileName, - manifestOrig.getPath(), hello.getPath() }); - check(status); + int status = JAR_TOOL.run(out, err, "cfm", jarFileName, + manifestOrig.getPath(), hello.getPath()); + check(status == 0); // Create a new manifest, to use in updating the jar file. File manifestUpdate = File.createTempFile("manifestUpdate", ".txt"); @@ -122,10 +122,9 @@ public class UpdateManifest { pw.close(); // Update jar file with manifest - jartool = new Main(out, err, "jar"); - status = jartool.run( - new String[] { "ufm", jarFileName, manifestUpdate.getPath() }); - check(status); + status = JAR_TOOL.run(out, err, "ufm", + jarFileName, manifestUpdate.getPath()); + check(status == 0); // Extract jar, and verify contents of manifest file File f = new File(jarFileName); diff --git a/jdk/test/tools/jar/index/MetaInf.java b/jdk/test/tools/jar/index/MetaInf.java index 29108c72d2f..1353acf87f3 100644 --- a/jdk/test/tools/jar/index/MetaInf.java +++ b/jdk/test/tools/jar/index/MetaInf.java @@ -24,17 +24,21 @@ /* * @test * @bug 4408526 6854795 - * @modules jdk.jartool/sun.tools.jar + * @modules jdk.jartool * @summary Index the non-meta files in META-INF, such as META-INF/services. */ import java.io.*; import java.util.Arrays; import java.util.jar.*; -import sun.tools.jar.Main; +import java.util.spi.ToolProvider; import java.util.zip.ZipFile; public class MetaInf { + static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); static String jarName = "a.jar"; static String INDEX = "META-INF/INDEX.LIST"; @@ -43,7 +47,7 @@ public class MetaInf { System.getProperty("test.src") + File.separatorChar + "jarcontents"; static void run(String ... args) { - if (! new Main(System.out, System.err, "jar").run(args)) + if (JAR_TOOL.run(System.out, System.err, args) != 0) throw new Error("jar failed: args=" + Arrays.toString(args)); } diff --git a/jdk/test/tools/jlink/JLinkTest.java b/jdk/test/tools/jlink/JLinkTest.java index d6e9d1bca92..2215bef8ec0 100644 --- a/jdk/test/tools/jlink/JLinkTest.java +++ b/jdk/test/tools/jlink/JLinkTest.java @@ -32,13 +32,13 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.spi.ToolProvider; import java.util.stream.Stream; import jdk.tools.jlink.plugin.Plugin; import jdk.tools.jlink.internal.PluginRepository; import tests.Helper; import tests.JImageGenerator; -import tests.JImageGenerator.InMemoryFile; /* * @test @@ -48,13 +48,17 @@ import tests.JImageGenerator.InMemoryFile; * @modules java.base/jdk.internal.jimage * jdk.jdeps/com.sun.tools.classfile * jdk.jlink/jdk.tools.jlink.internal - * jdk.jlink/jdk.tools.jmod * jdk.jlink/jdk.tools.jimage * jdk.compiler * @build tests.* * @run main/othervm -Xmx1g JLinkTest */ public class JLinkTest { + static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") + .orElseThrow(() -> + new RuntimeException("jlink tool not found") + ); + // number of built-in plugins from jdk.jlink module private static int getNumJlinkPlugins() { ModuleDescriptor desc = Plugin.class.getModule().getDescriptor(); @@ -180,7 +184,8 @@ public class JLinkTest { { // Help StringWriter writer = new StringWriter(); - jdk.tools.jlink.internal.Main.run(new String[]{"--help"}, new PrintWriter(writer)); + PrintWriter pw = new PrintWriter(writer); + JLINK_TOOL.run(pw, pw, "--help"); String output = writer.toString(); if (output.split("\n").length < 10) { System.err.println(output); @@ -202,7 +207,9 @@ public class JLinkTest { { // List plugins StringWriter writer = new StringWriter(); - jdk.tools.jlink.internal.Main.run(new String[]{"--list-plugins"}, new PrintWriter(writer)); + PrintWriter pw = new PrintWriter(writer); + + JLINK_TOOL.run(pw, pw, "--list-plugins"); String output = writer.toString(); long number = Stream.of(output.split("\\R")) .filter((s) -> s.matches("Plugin Name:.*")) diff --git a/jdk/test/tools/jlink/basic/BasicTest.java b/jdk/test/tools/jlink/basic/BasicTest.java index 780cbca9cbc..6ddc4a190f9 100644 --- a/jdk/test/tools/jlink/basic/BasicTest.java +++ b/jdk/test/tools/jlink/basic/BasicTest.java @@ -27,8 +27,7 @@ * @author Andrei Eremeev * @library /lib/testlibrary * @modules java.base/jdk.internal.module - * jdk.jlink/jdk.tools.jlink.internal - * jdk.jlink/jdk.tools.jmod + * jdk.jlink * jdk.compiler * @build jdk.testlibrary.ProcessTools * jdk.testlibrary.OutputAnalyzer @@ -44,11 +43,21 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.spi.ToolProvider; import jdk.testlibrary.OutputAnalyzer; import jdk.testlibrary.ProcessTools; public class BasicTest { + static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") + .orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); + + static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink") + .orElseThrow(() -> + new RuntimeException("jlink tool not found") + ); private final Path jdkHome = Paths.get(System.getProperty("test.jdk")); private final Path jdkMods = jdkHome.resolve("jmods"); @@ -110,20 +119,22 @@ public class BasicTest { "--add-modules", modName, "--output", image.toString()); Collections.addAll(args, options); - int rc = jdk.tools.jlink.internal.Main.run(args.toArray(new String[args.size()]), new PrintWriter(System.out)); + + PrintWriter pw = new PrintWriter(System.out); + int rc = JLINK_TOOL.run(pw, pw, args.toArray(new String[args.size()])); if (rc != 0) { throw new AssertionError("Jlink failed: rc = " + rc); } } private void runJmod(String cp, String modName) { - int rc = jdk.tools.jmod.Main.run(new String[] { + int rc = JMOD_TOOL.run(System.out, System.out, new String[] { "create", "--class-path", cp, "--module-version", "1.0", "--main-class", "jdk.test.Test", jmods.resolve(modName + ".jmod").toString(), - }, System.out); + }); if (rc != 0) { throw new AssertionError("Jmod failed: rc = " + rc); } diff --git a/jdk/test/tools/jmod/JmodNegativeTest.java b/jdk/test/tools/jmod/JmodNegativeTest.java index 317587f5fb5..02a3791dfac 100644 --- a/jdk/test/tools/jmod/JmodNegativeTest.java +++ b/jdk/test/tools/jmod/JmodNegativeTest.java @@ -24,8 +24,8 @@ /* * @test * @library /lib/testlibrary - * @modules jdk.jlink/jdk.tools.jmod - * jdk.compiler + * @modules jdk.compiler + * jdk.jlink * @build jdk.testlibrary.FileUtils CompilerUtils * @run testng JmodNegativeTest * @summary Negative tests for jmod @@ -39,6 +39,7 @@ import java.util.Arrays; import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; +import java.util.spi.ToolProvider; import java.util.zip.ZipOutputStream; import jdk.testlibrary.FileUtils; import org.testng.annotations.BeforeTest; @@ -51,6 +52,11 @@ import static org.testng.Assert.assertTrue; public class JmodNegativeTest { + static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") + .orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); + static final String TEST_SRC = System.getProperty("test.src", "."); static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); static final Path EXPLODED_DIR = Paths.get("build"); @@ -515,7 +521,7 @@ public class JmodNegativeTest { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); System.out.println("jmod " + Arrays.asList(args)); - int ec = jdk.tools.jmod.Main.run(args, ps); + int ec = JMOD_TOOL.run(ps, ps, args); return new JmodResult(ec, new String(baos.toByteArray(), UTF_8)); } diff --git a/jdk/test/tools/jmod/JmodTest.java b/jdk/test/tools/jmod/JmodTest.java index 064ba585297..5be6a692daf 100644 --- a/jdk/test/tools/jmod/JmodTest.java +++ b/jdk/test/tools/jmod/JmodTest.java @@ -24,8 +24,8 @@ /* * @test * @library /lib/testlibrary - * @modules jdk.jlink/jdk.tools.jmod - * jdk.compiler + * @modules jdk.compiler + * jdk.jlink * @build jdk.testlibrary.FileUtils CompilerUtils * @run testng JmodTest * @summary Basic test for jmod @@ -38,6 +38,7 @@ import java.nio.file.*; import java.util.*; import java.util.function.Consumer; import java.util.regex.Pattern; +import java.util.spi.ToolProvider; import java.util.stream.Stream; import jdk.testlibrary.FileUtils; import org.testng.annotations.BeforeTest; @@ -51,6 +52,11 @@ import static org.testng.Assert.*; public class JmodTest { + static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") + .orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); + static final String TEST_SRC = System.getProperty("test.src", "."); static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); static final Path EXPLODED_DIR = Paths.get("build"); @@ -479,7 +485,7 @@ public class JmodTest { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream ps = new PrintStream(baos); System.out.println("jmod " + Arrays.asList(args)); - int ec = jdk.tools.jmod.Main.run(args, ps); + int ec = JMOD_TOOL.run(ps, ps, args); return new JmodResult(ec, new String(baos.toByteArray(), UTF_8)); } diff --git a/jdk/test/tools/jmod/hashes/HashesTest.java b/jdk/test/tools/jmod/hashes/HashesTest.java index 616d393b97a..e01ecdb8046 100644 --- a/jdk/test/tools/jmod/hashes/HashesTest.java +++ b/jdk/test/tools/jmod/hashes/HashesTest.java @@ -27,8 +27,7 @@ * @author Andrei Eremeev * @library /lib/testlibrary * @modules java.base/jdk.internal.module - * jdk.jlink/jdk.tools.jlink.internal - * jdk.jlink/jdk.tools.jmod + * jdk.jlink * jdk.compiler * @build CompilerUtils * @run testng HashesTest @@ -53,6 +52,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.spi.ToolProvider; import java.util.stream.Collectors; import jdk.internal.module.ConfigurableModuleFinder; @@ -63,6 +63,10 @@ import org.testng.annotations.Test; import static org.testng.Assert.*; public class HashesTest { + static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") + .orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); private final Path testSrc = Paths.get(System.getProperty("test.src")); private final Path modSrc = testSrc.resolve("src"); @@ -204,7 +208,7 @@ public class HashesTest { } private void runJmod(List args) { - int rc = jdk.tools.jmod.Main.run(args.toArray(new String[args.size()]), System.out); + int rc = JMOD_TOOL.run(System.out, System.out, args.toArray(new String[args.size()])); System.out.println("jmod options: " + args.stream().collect(Collectors.joining(" "))); if (rc != 0) { throw new AssertionError("Jmod failed: rc = " + rc); diff --git a/jdk/test/tools/launcher/modules/addexports/AddExportsTest.java b/jdk/test/tools/launcher/modules/addexports/AddExportsTest.java index 8142c4af193..cc9b1743855 100644 --- a/jdk/test/tools/launcher/modules/addexports/AddExportsTest.java +++ b/jdk/test/tools/launcher/modules/addexports/AddExportsTest.java @@ -202,7 +202,7 @@ public class AddExportsTest { /** - * --add-exports can only be specified once + * --add-exports allows duplicates */ public void testWithDuplicateOption() throws Exception { @@ -212,10 +212,40 @@ public class AddExportsTest { "-version") .outputTo(System.out) .errorTo(System.out) - .shouldContain("specified more than once") .getExitValue(); - assertTrue(exitValue != 0); + assertTrue(exitValue == 0); + } + + + /** + * Exercise --add-exports with unknown values. Warning is emitted. + */ + @Test(dataProvider = "unknownvalues") + public void testWithUnknownValue(String value, String ignore) throws Exception { + + // --add-exports $VALUE -version + int exitValue = + executeTestJava("--add-exports", value, + "-version") + .stderrShouldMatch("WARNING: .*.monkey.*") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + + assertTrue(exitValue == 0); + } + + @DataProvider(name = "unknownvalues") + public Object[][] unknownValues() { + return new Object[][]{ + + { "java.base/jdk.internal.misc=sun.monkey", null }, // unknown target + { "java.monkey/sun.monkey=ALL-UNNAMED", null }, // unknown module + { "java.base/sun.monkey=ALL-UNNAMED", null }, // unknown package + { "java.monkey/sun.monkey=ALL-UNNAMED", null }, // unknown module/package + + }; } @@ -241,10 +271,6 @@ public class AddExportsTest { return new Object[][]{ { "java.base/jdk.internal.misc", null }, // missing target - { "java.base/jdk.internal.misc=sun.monkey", null }, // unknown target - { "java.monkey/sun.monkey=ALL-UNNAMED", null }, // unknown module - { "java.base/sun.monkey=ALL-UNNAMED", null }, // unknown package - { "java.monkey/sun.monkey=ALL-UNNAMED", null }, // unknown module/package { "java.base=ALL-UNNAMED", null }, // missing package { "java.base/=ALL-UNNAMED", null } // missing package diff --git a/jdk/test/tools/launcher/modules/addreads/AddReadsTest.java b/jdk/test/tools/launcher/modules/addreads/AddReadsTest.java index 24e5dbbf110..6d0b4a7eaf6 100644 --- a/jdk/test/tools/launcher/modules/addreads/AddReadsTest.java +++ b/jdk/test/tools/launcher/modules/addreads/AddReadsTest.java @@ -182,28 +182,43 @@ public class AddReadsTest { "--add-reads", "m1=java.xml", "--add-reads", "m1=junit", "-m", MAIN) - .shouldContain("specified more than once") .getExitValue(); - assertTrue(exitValue != 0); + assertTrue(exitValue == 0); } /** - * Exercise --add-reads with bad values + * Exercise --add-reads with missing source + */ + public void testWithMissingSource() throws Exception { + + // --add-exports $VALUE -version + assertTrue(run("--add-reads", "java.base", "-version").getExitValue() != 0); + } + + + /** + * Exercise --add-reads with unknown source/target module. + * Warning is emitted. */ @Test(dataProvider = "badvalues") public void testWithBadValue(String value, String ignore) throws Exception { // --add-exports $VALUE -version - assertTrue(run("--add-reads", value, "-version").getExitValue() != 0); + int exitValue = run("--add-reads", value, "-version") + .stderrShouldMatch("WARNING: Unknown module: .*.monkey") + .outputTo(System.out) + .errorTo(System.out) + .getExitValue(); + + assertTrue(exitValue == 0); } @DataProvider(name = "badvalues") public Object[][] badValues() { return new Object[][]{ - { "java.base", null }, // missing source { "java.monkey=java.base", null }, // unknown module { "java.base=sun.monkey", null }, // unknown source diff --git a/jdk/test/tools/launcher/modules/basic/BasicTest.java b/jdk/test/tools/launcher/modules/basic/BasicTest.java index 233fa29e00b..3256f354c78 100644 --- a/jdk/test/tools/launcher/modules/basic/BasicTest.java +++ b/jdk/test/tools/launcher/modules/basic/BasicTest.java @@ -24,9 +24,9 @@ /** * @test * @library /lib/testlibrary - * @modules jdk.jartool/sun.tools.jar - * jdk.jlink/jdk.tools.jmod - * jdk.compiler + * @modules jdk.compiler + * jdk.jartool + * jdk.jlink * @build BasicTest CompilerUtils jdk.testlibrary.* * @run testng BasicTest * @summary Basic test of starting an application as a module @@ -36,6 +36,7 @@ import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.spi.ToolProvider; import jdk.testlibrary.ProcessTools; @@ -46,6 +47,14 @@ import static org.testng.Assert.*; @Test public class BasicTest { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + private static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") + .orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); @@ -132,10 +141,8 @@ public class BasicTest { "--main-class=" + MAIN_CLASS, "-C", classes, "." }; - boolean success - = new sun.tools.jar.Main(System.out, System.out, "jar") - .run(args); - assertTrue(success); + int rc = JAR_TOOL.run(System.out, System.out, args); + assertTrue(rc == 0); // java --module-path mlib -module $TESTMODULE int exitValue = exec("--module-path", dir.toString(), @@ -164,8 +171,8 @@ public class BasicTest { "--main-class", MAIN_CLASS, jmod }; - jdk.tools.jmod.JmodTask task = new jdk.tools.jmod.JmodTask(); - assertEquals(task.run(args), 0); + + assertEquals(JMOD_TOOL.run(System.out, System.out, args), 0); // java --module-path mods --module $TESTMODULE int exitValue = exec("--module-path", dir.toString(), @@ -229,10 +236,8 @@ public class BasicTest { "--file=" + jar, "-C", classes, "." }; - boolean success - = new sun.tools.jar.Main(System.out, System.out, "jar") - .run(args); - assertTrue(success); + int rc = JAR_TOOL.run(System.out, System.out, args); + assertTrue(rc == 0); // java --module-path mods -m $TESTMODULE int exitValue = exec("--module-path", dir.toString(), "-m", TEST_MODULE); diff --git a/jdk/test/tools/launcher/modules/dryrun/DryRunTest.java b/jdk/test/tools/launcher/modules/dryrun/DryRunTest.java index acf65bc1475..fe9a293be57 100644 --- a/jdk/test/tools/launcher/modules/dryrun/DryRunTest.java +++ b/jdk/test/tools/launcher/modules/dryrun/DryRunTest.java @@ -26,7 +26,7 @@ * @bug 8159596 * @library /lib/testlibrary * @modules jdk.compiler - * jdk.jartool/sun.tools.jar + * jdk.jartool * @build DryRunTest CompilerUtils jdk.testlibrary.ProcessTools * @run testng DryRunTest * @summary Test java --dry-run @@ -37,6 +37,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.spi.ToolProvider; import jdk.testlibrary.ProcessTools; @@ -78,8 +79,8 @@ public class DryRunTest { Files.createDirectories(LIBS_DIR); // create JAR files with no module-info.class - assertTrue(jar(M_MODULE, "p/Lib.class")); - assertTrue(jar(TEST_MODULE, "jdk/test/Main.class")); + assertTrue(jar(M_MODULE, "p/Lib.class") == 0); + assertTrue(jar(TEST_MODULE, "jdk/test/Main.class") == 0); } /** @@ -197,7 +198,12 @@ public class DryRunTest { assertTrue(exitValue != 0); } - private static boolean jar(String name, String entries) throws IOException { + private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar") + .orElseThrow(() -> + new RuntimeException("jar tool not found") + ); + + private static int jar(String name, String entries) throws IOException { Path jar = LIBS_DIR.resolve(name + ".jar"); // jar --create ... @@ -207,8 +213,6 @@ public class DryRunTest { "--file=" + jar, "-C", classes, entries }; - boolean success - = new sun.tools.jar.Main(System.out, System.out, "jar").run(args); - return success; + return JAR_TOOL.run(System.out, System.out, args); } } diff --git a/jdk/test/tools/lib/tests/JImageGenerator.java b/jdk/test/tools/lib/tests/JImageGenerator.java index beaf2dbe0b6..59e7d37cbce 100644 --- a/jdk/test/tools/lib/tests/JImageGenerator.java +++ b/jdk/test/tools/lib/tests/JImageGenerator.java @@ -338,6 +338,10 @@ public class JImageGenerator { } public static class JModTask { + static final java.util.spi.ToolProvider JMOD_TOOL = + java.util.spi.ToolProvider.findFirst("jmod").orElseThrow(() -> + new RuntimeException("jmod tool not found") + ); private final List classpath = new ArrayList<>(); private final List libs = new ArrayList<>(); @@ -477,7 +481,8 @@ public class JImageGenerator { String[] args = optionsJMod(cmd); System.err.println("jmod options: " + optionsPrettyPrint(args)); ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int exitCode = jdk.tools.jmod.Main.run(args, new PrintStream(baos)); + PrintStream ps = new PrintStream(baos); + int exitCode = JMOD_TOOL.run(ps, ps, args); String msg = new String(baos.toByteArray()); return new Result(exitCode, msg, output); } @@ -556,6 +561,10 @@ public class JImageGenerator { } public static class JLinkTask { + static final java.util.spi.ToolProvider JLINK_TOOL = + java.util.spi.ToolProvider.findFirst("jlink").orElseThrow(() -> + new RuntimeException("jlink tool not found") + ); private final List jars = new ArrayList<>(); private final List jmods = new ArrayList<>(); @@ -691,7 +700,8 @@ public class JImageGenerator { String[] args = optionsJLink(); System.err.println("jlink options: " + optionsPrettyPrint(args)); StringWriter writer = new StringWriter(); - int exitCode = jdk.tools.jlink.internal.Main.run(args, new PrintWriter(writer)); + PrintWriter pw = new PrintWriter(writer); + int exitCode = JLINK_TOOL.run(pw, pw, args); return new Result(exitCode, writer.toString(), output); } @@ -699,7 +709,8 @@ public class JImageGenerator { String[] args = optionsPostProcessJLink(); System.err.println("jlink options: " + optionsPrettyPrint(args)); StringWriter writer = new StringWriter(); - int exitCode = jdk.tools.jlink.internal.Main.run(args, new PrintWriter(writer)); + PrintWriter pw = new PrintWriter(writer); + int exitCode = JLINK_TOOL.run(pw, pw, args); return new Result(exitCode, writer.toString(), output); } } diff --git a/langtools/.hgtags b/langtools/.hgtags index 81a826500af..a116158f8b1 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -381,3 +381,4 @@ af5eb8f3ffd21288305a54ea177ffad75021a741 jdk-9+135 c8f02f0ecbd7cd6700f47416e4b7e9d5ec20ad77 jdk-9+136 dd56c243c199a540c9f1fbff4855f0934b32a9d0 jdk-9+137 90dd93e668a521642382561c47abe96ee2e065b7 jdk-9+138 +17a82cb0e4b480e97021691d39917f15e3f7b653 jdk-9+139 diff --git a/langtools/ASSEMBLY_EXCEPTION b/langtools/ASSEMBLY_EXCEPTION index 8b7ac1d0813..065b8d90239 100644 --- a/langtools/ASSEMBLY_EXCEPTION +++ b/langtools/ASSEMBLY_EXCEPTION @@ -1,27 +1,27 @@ OPENJDK ASSEMBLY EXCEPTION -The OpenJDK source code made available by Sun at openjdk.java.net and -openjdk.dev.java.net ("OpenJDK Code") is distributed under the terms of the -GNU General Public License version 2 +The OpenJDK source code made available by Oracle America, Inc. (Oracle) at +openjdk.java.net ("OpenJDK Code") is distributed under the terms of the GNU +General Public License version 2 only ("GPL2"), with the following clarification and special exception. Linking this OpenJDK Code statically or dynamically with other code is making a combined work based on this library. Thus, the terms and conditions of GPL2 cover the whole combination. - As a special exception, Sun gives you permission to link this - OpenJDK Code with certain code licensed by Sun as indicated at + As a special exception, Oracle gives you permission to link this + OpenJDK Code with certain code licensed by Oracle as indicated at http://openjdk.java.net/legal/exception-modules-2007-05-08.html ("Designated Exception Modules") to produce an executable, regardless of the license terms of the Designated Exception Modules, and to copy and distribute the resulting executable under GPL2, provided that the Designated Exception Modules continue to be - governed by the licenses under which they were offered by Sun. + governed by the licenses under which they were offered by Oracle. -As such, it allows licensees and sublicensees of Sun's GPL2 OpenJDK Code to -build an executable that includes those portions of necessary code that Sun -could not provide under GPL2 (or that Sun has provided under GPL2 with the -Classpath exception). If you modify or add to the OpenJDK code, that new -GPL2 code may still be combined with Designated Exception Modules if the -new code is made subject to this exception by its copyright holder. +As such, it allows licensees and sublicensees of Oracle's GPL2 OpenJDK Code +to build an executable that includes those portions of necessary code that +Oracle could not provide under GPL2 (or that Oracle has provided under GPL2 +with the Classpath exception). If you modify or add to the OpenJDK code, +that new GPL2 code may still be combined with Designated Exception Modules +if the new code is made subject to this exception by its copyright holder. diff --git a/langtools/make/CompileInterim.gmk b/langtools/make/CompileInterim.gmk index 171c830fb1a..33a23802306 100644 --- a/langtools/make/CompileInterim.gmk +++ b/langtools/make/CompileInterim.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ define SetupInterimModule $$(wildcard $(SUPPORT_OUTPUTDIR)/gensrc/$(strip $1)), \ EXCLUDES := sun com/sun/tools/jdeps com/sun/tools/javap \ com/sun/tools/jdeprscan, \ - EXCLUDE_FILES := module-info.java, \ + EXCLUDE_FILES := module-info.java JavacToolProvider.java JavadocToolProvider.java, \ COPY := .gif .png .xml .css .js javax.tools.JavaCompilerTool, \ BIN := $(BUILDTOOLS_OUTPUTDIR)/override_modules/$(strip $1), \ ADD_JAVAC_FLAGS := -Xbootclasspath/p:$$(call PathList, \ diff --git a/langtools/make/tools/crules/MutableFieldsAnalyzer.java b/langtools/make/tools/crules/MutableFieldsAnalyzer.java index 0b082aca0ba..bae6b4d6836 100644 --- a/langtools/make/tools/crules/MutableFieldsAnalyzer.java +++ b/langtools/make/tools/crules/MutableFieldsAnalyzer.java @@ -111,6 +111,8 @@ public class MutableFieldsAnalyzer extends AbstractCodingRulesAnalyzer { "loadMethod"); ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$VMHelper", "vmClass", "getRuntimeArgumentsMethod"); + ignoreFields("com.sun.tools.javac.util.JDK9Wrappers$JmodFile", + "jmodFileClass", "checkMagicMethod"); } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeFactory.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeFactory.java index 945bf27a08a..c7259d4ffef 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeFactory.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreeFactory.java @@ -112,12 +112,11 @@ public interface DocTreeFactory { /** * Create a new {@code DocCommentTree} object, to represent a complete doc comment. - * @param firstSentence the first sentence of the doc comment - * @param body the body of the doc comment following the first sentence + * @param fullBody the entire body of the doc comment * @param tags the block tags in the doc comment * @return a {@code DocCommentTree} object */ - DocCommentTree newDocCommentTree(List firstSentence, List body, List tags); + DocCommentTree newDocCommentTree(List fullBody, List tags); /** * Create a new {@code DocRootTree} object, to represent an {@code {@docroot} } tag. diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/TreePathScanner.java b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/TreePathScanner.java index 46a3e1e547c..ab05005012f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/TreePathScanner.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/TreePathScanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,10 @@ import com.sun.source.tree.*; * Inside your method, call super.visitXYZ to visit descendant * nodes. * + * @apiNote + * In order to initialize the "current path", the scan must be + * started by calling one of the {@code scan} methods. + * * @author Jonathan Gibbons * @since 1.6 */ @@ -58,6 +62,13 @@ public class TreePathScanner extends TreeScanner { /** * Scans a single node. * The current path is updated for the duration of the scan. + * + * @apiNote This method should normally only be called by the + * scanner's {@code visit} methods, as part of an ongoing scan + * initiated by {@link #scan(TreePath,Object) scan(TreePath, P)}. + * The one exception is that it may also be called to initiate + * a full scan of a {@link CompilationUnitTree}. + * * @return the result value from the visit method */ @Override diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index be396ba3ebc..2743702d11d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -4415,6 +4415,7 @@ public class Attr extends JCTree.Visitor { chk.checkDeprecatedAnnotation(env.tree.pos(), c); chk.checkClassOverrideEqualsAndHashIfNeeded(env.tree.pos(), c); chk.checkFunctionalInterface((JCClassDecl) env.tree, c); + chk.checkLeaksNotAccessible(env, (JCClassDecl) env.tree); } finally { env.info.returnResult = prevReturnRes; log.useSource(prev); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index 5767f9c45e4..1a774450eac 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -31,10 +31,13 @@ import javax.tools.JavaFileManager; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Attribute.Compound; +import com.sun.tools.javac.code.Directive.ExportsDirective; +import com.sun.tools.javac.code.Directive.RequiresDirective; import com.sun.tools.javac.comp.Annotate.AnnotationTypeMetadata; import com.sun.tools.javac.jvm.*; import com.sun.tools.javac.resources.CompilerProperties.Errors; import com.sun.tools.javac.resources.CompilerProperties.Fragments; +import com.sun.tools.javac.resources.CompilerProperties.Warnings; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; @@ -3661,4 +3664,178 @@ public class Check { } } + public void checkLeaksNotAccessible(Env env, JCClassDecl check) { + JCCompilationUnit toplevel = env.toplevel; + + if ( toplevel.modle == syms.unnamedModule + || toplevel.modle == syms.noModule + || (check.sym.flags() & COMPOUND) != 0) { + return ; + } + + ExportsDirective currentExport = findExport(toplevel.packge); + + if ( currentExport == null //not exported + || currentExport.modules != null) //don't check classes in qualified export + return ; + + new TreeScanner() { + Lint lint = env.info.lint; + boolean inSuperType; + + @Override + public void visitBlock(JCBlock tree) { + } + @Override + public void visitMethodDef(JCMethodDecl tree) { + if (!isAPISymbol(tree.sym)) + return; + Lint prevLint = lint; + try { + lint = lint.augment(tree.sym); + if (lint.isEnabled(LintCategory.EXPORTS)) { + super.visitMethodDef(tree); + } + } finally { + lint = prevLint; + } + } + @Override + public void visitVarDef(JCVariableDecl tree) { + if (!isAPISymbol(tree.sym) && tree.sym.owner.kind != MTH) + return; + Lint prevLint = lint; + try { + lint = lint.augment(tree.sym); + if (lint.isEnabled(LintCategory.EXPORTS)) { + scan(tree.mods); + scan(tree.vartype); + } + } finally { + lint = prevLint; + } + } + @Override + public void visitClassDef(JCClassDecl tree) { + if (tree != check) + return ; + + if (!isAPISymbol(tree.sym)) + return ; + + Lint prevLint = lint; + try { + lint = lint.augment(tree.sym); + if (lint.isEnabled(LintCategory.EXPORTS)) { + scan(tree.mods); + scan(tree.typarams); + try { + inSuperType = true; + scan(tree.extending); + scan(tree.implementing); + } finally { + inSuperType = false; + } + scan(tree.defs); + } + } finally { + lint = prevLint; + } + } + @Override + public void visitTypeApply(JCTypeApply tree) { + scan(tree.clazz); + boolean oldInSuperType = inSuperType; + try { + inSuperType = false; + scan(tree.arguments); + } finally { + inSuperType = oldInSuperType; + } + } + @Override + public void visitIdent(JCIdent tree) { + Symbol sym = TreeInfo.symbol(tree); + if (sym.kind == TYP && !sym.type.hasTag(TYPEVAR)) { + checkVisible(tree.pos(), sym, toplevel.packge, inSuperType); + } + } + + @Override + public void visitSelect(JCFieldAccess tree) { + Symbol sym = TreeInfo.symbol(tree); + Symbol sitesym = TreeInfo.symbol(tree.selected); + if (sym.kind == TYP && sitesym.kind == PCK) { + checkVisible(tree.pos(), sym, toplevel.packge, inSuperType); + } else { + super.visitSelect(tree); + } + } + + @Override + public void visitAnnotation(JCAnnotation tree) { + if (tree.attribute.type.tsym.getAnnotation(java.lang.annotation.Documented.class) != null) + super.visitAnnotation(tree); + } + + }.scan(check); + } + //where: + private ExportsDirective findExport(PackageSymbol pack) { + for (ExportsDirective d : pack.modle.exports) { + if (d.packge == pack) + return d; + } + + return null; + } + private boolean isAPISymbol(Symbol sym) { + while (sym.kind != PCK) { + if ((sym.flags() & Flags.PUBLIC) == 0 && (sym.flags() & Flags.PROTECTED) == 0) { + return false; + } + sym = sym.owner; + } + return true; + } + private void checkVisible(DiagnosticPosition pos, Symbol what, PackageSymbol inPackage, boolean inSuperType) { + if (!isAPISymbol(what) && !inSuperType) { //package private/private element + log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessible(kindName(what), what, what.packge().modle)); + return ; + } + + PackageSymbol whatPackage = what.packge(); + ExportsDirective whatExport = findExport(whatPackage); + ExportsDirective inExport = findExport(inPackage); + + if (whatExport == null) { //package not exported: + log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleUnexported(kindName(what), what, what.packge().modle)); + return ; + } + + if (whatExport.modules != null) { + if (inExport.modules == null || !whatExport.modules.containsAll(inExport.modules)) { + log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleUnexportedQualified(kindName(what), what, what.packge().modle)); + } + } + + if (whatPackage.modle != inPackage.modle && whatPackage.modle != syms.java_base) { + //check that relativeTo.modle requires public what.modle, somehow: + List todo = List.of(inPackage.modle); + + while (todo.nonEmpty()) { + ModuleSymbol current = todo.head; + todo = todo.tail; + if (current == whatPackage.modle) + return ; //OK + for (RequiresDirective req : current.requires) { + if (req.isPublic()) { + todo = todo.prepend(req.module); + } + } + } + + log.warning(LintCategory.EXPORTS, pos, Warnings.LeaksNotAccessibleNotRequiredPublic(kindName(what), what, what.packge().modle)); + } + } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java index 8cab1840f8f..4e32325ef11 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java @@ -78,6 +78,7 @@ import com.sun.tools.javac.resources.CompilerProperties.Errors; import com.sun.tools.javac.resources.CompilerProperties.Warnings; import com.sun.tools.javac.util.DefinedBy; import com.sun.tools.javac.util.DefinedBy.Api; +import com.sun.tools.javac.util.JDK9Wrappers; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.jvm.ModuleNameReader; @@ -1103,6 +1104,11 @@ public class Locations { if (p.getFileName().toString().endsWith(".jmod")) { try { + // check if the JMOD file is valid + JDK9Wrappers.JmodFile.checkMagic(p); + + // No JMOD file system. Use JarFileSystem to + // workaround for now FileSystem fs = fileSystems.get(p); if (fs == null) { URI uri = URI.create("jar:" + p.toUri()); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/CommandLine.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/CommandLine.java index 546f64d6a86..9fc54414efb 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/CommandLine.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/CommandLine.java @@ -27,7 +27,6 @@ package com.sun.tools.javac.main; import java.io.IOException; import java.io.Reader; -import java.io.StreamTokenizer; import java.nio.file.Files; import java.nio.file.Paths; @@ -51,10 +50,11 @@ public class CommandLine { * '@file' argument replaced with the resulting tokens. Recursive command * files are not supported. The '@' character itself can be quoted with * the sequence '@@'. + * @param args the arguments that may contain @files + * @return the arguments, with @files expanded + * @throws IOException if there is a problem reading any of the @files */ - public static String[] parse(String[] args) - throws IOException - { + public static String[] parse(String[] args) throws IOException { ListBuffer newArgs = new ListBuffer<>(); for (String arg : args) { if (arg.length() > 1 && arg.charAt(0) == '@') { @@ -71,19 +71,120 @@ public class CommandLine { return newArgs.toList().toArray(new String[newArgs.length()]); } - private static void loadCmdFile(String name, ListBuffer args) - throws IOException - { + private static void loadCmdFile(String name, ListBuffer args) throws IOException { try (Reader r = Files.newBufferedReader(Paths.get(name))) { - StreamTokenizer st = new StreamTokenizer(r); - st.resetSyntax(); - st.wordChars(' ', 255); - st.whitespaceChars(0, ' '); - st.commentChar('#'); - st.quoteChar('"'); - st.quoteChar('\''); - while (st.nextToken() != StreamTokenizer.TT_EOF) { - args.append(st.sval); + Tokenizer t = new Tokenizer(r); + String s; + while ((s = t.nextToken()) != null) { + args.append(s); + } + } + } + + public static class Tokenizer { + private final Reader in; + private int ch; + + public Tokenizer(Reader in) throws IOException { + this.in = in; + ch = in.read(); + } + + public String nextToken() throws IOException { + skipWhite(); + if (ch == -1) { + return null; + } + + StringBuilder sb = new StringBuilder(); + char quoteChar = 0; + + while (ch != -1) { + switch (ch) { + case ' ': + case '\t': + case '\f': + if (quoteChar == 0) { + return sb.toString(); + } + sb.append((char) ch); + break; + + case '\n': + case '\r': + return sb.toString(); + + case '\'': + case '"': + if (quoteChar == 0) { + quoteChar = (char) ch; + } else if (quoteChar == ch) { + quoteChar = 0; + } else { + sb.append((char) ch); + } + break; + + case '\\': + if (quoteChar != 0) { + ch = in.read(); + switch (ch) { + case '\n': + case '\r': + while (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f') { + ch = in.read(); + } + continue; + + case 'n': + ch = '\n'; + break; + case 'r': + ch = '\r'; + break; + case 't': + ch = '\t'; + break; + case 'f': + ch = '\f'; + break; + } + } + sb.append((char) ch); + break; + + default: + sb.append((char) ch); + } + + ch = in.read(); + } + + return sb.toString(); + } + + void skipWhite() throws IOException { + while (ch != -1) { + switch (ch) { + case ' ': + case '\t': + case '\n': + case '\r': + case '\f': + break; + + case '#': + ch = in.read(); + while (ch != '\n' && ch != '\r' && ch != -1) { + ch = in.read(); + } + break; + + default: + return; + } + + ch = in.read(); } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavacToolProvider.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavacToolProvider.java new file mode 100644 index 00000000000..bd1415a9abc --- /dev/null +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavacToolProvider.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.main; + +import java.io.PrintWriter; +import java.util.spi.ToolProvider; + +/** + * An implementation of the {@link java.util.spi.ToolProvider ToolProvider} SPI, + * providing access to JDK Java compiler, javac. + * + * @since 9 + */ +// This is currently a stand-alone top-level class so that it can easily be excluded +// from interims builds of javac, used while building JDK. +public class JavacToolProvider implements ToolProvider { + public String name() { + return "javac"; + } + + public int run(PrintWriter out, PrintWriter err, String... args) { + Main compiler = new Main("javac", out, err); + return compiler.compile(args).exitCode; + } +} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java index 4d5cd927cf8..408189dcc4f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Main.java @@ -119,6 +119,18 @@ public class Main { this.stdOut = this.stdErr = out; } + /** + * Construct a compiler instance. + * @param name the name of this tool + * @param out a stream to which to write expected output + * @param err a stream to which to write diagnostic output + */ + public Main(String name, PrintWriter out, PrintWriter err) { + this.ownName = name; + this.stdOut = out; + this.stdErr = err; + } + /** Report a usage error. */ void error(String key, Object... args) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 950e128b8ca..f183212aa70 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -2865,6 +2865,19 @@ compiler.err.invalid.module.specifier=\ compiler.warn.service.provided.but.not.exported.or.used=\ service interface provided but not exported or used +# 0: kind name, 1: symbol, 2: symbol +compiler.warn.leaks.not.accessible=\ + {0} {1} in module {2} is not accessible to clients that require this module +# 0: kind name, 1: symbol, 2: symbol +compiler.warn.leaks.not.accessible.unexported=\ + {0} {1} in module {2} is not exported +# 0: kind name, 1: symbol, 2: symbol +compiler.warn.leaks.not.accessible.not.required.public=\ + {0} {1} in module {2} is not indirectly exported using 'requires public' +# 0: kind name, 1: symbol, 2: symbol +compiler.warn.leaks.not.accessible.unexported.qualified=\ + {0} {1} in module {2} may not be visible to all clients that require this module + ### # errors related to options diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java index 01b1dd7a56d..b7b6c1267b8 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java @@ -203,11 +203,10 @@ public class DocTreeMaker implements DocTreeFactory { * where the trees are being synthesized by a tool. */ @Override @DefinedBy(Api.COMPILER_TREE) - public DCDocComment newDocCommentTree(List firstSentence, List body, List tags) { + public DCDocComment newDocCommentTree(List fullBody, List tags) { ListBuffer lb = new ListBuffer<>(); - lb.addAll(cast(firstSentence)); - lb.addAll(cast(body)); - List fullBody = lb.toList(); + lb.addAll(cast(fullBody)); + List fBody = lb.toList(); // A dummy comment to keep the diagnostics logic happy. Comment c = new Comment() { @@ -231,8 +230,8 @@ public class DocTreeMaker implements DocTreeFactory { return false; } }; - - DCDocComment tree = new DCDocComment(c, fullBody, cast(firstSentence), cast(body), cast(tags)); + Pair, List> pair = splitBody(fullBody); + DCDocComment tree = new DCDocComment(c, fBody, pair.fst, pair.snd, cast(tags)); return tree; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Iterators.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Iterators.java index b30af24e914..24e0a02aaca 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Iterators.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Iterators.java @@ -46,7 +46,8 @@ public class Iterators { private final Iterator inputs; private final Function> convertor; - private Iterator currentIterator; + @SuppressWarnings("unchecked") + private Iterator currentIterator = EMPTY; public CompoundIterator(Iterable inputs, Function> convertor) { this.inputs = inputs.iterator(); @@ -54,10 +55,10 @@ public class Iterators { } public boolean hasNext() { - while (inputs.hasNext() && (currentIterator == null || !currentIterator.hasNext())) { - currentIterator = convertor.apply(inputs.next()); + if (currentIterator != null && !currentIterator.hasNext()) { + update(); } - return currentIterator != null && currentIterator.hasNext(); + return currentIterator != null; } public O next() { @@ -70,5 +71,25 @@ public class Iterators { public void remove() { throw new UnsupportedOperationException(); } + + private void update() { + while (inputs.hasNext()) { + currentIterator = convertor.apply(inputs.next()); + if (currentIterator.hasNext()) return; + } + currentIterator = null; + } } + + @SuppressWarnings("rawtypes") + private final static Iterator EMPTY = new Iterator() { + public boolean hasNext() { + return false; + } + + @Override + public Object next() { + return null; + } + }; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JDK9Wrappers.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JDK9Wrappers.java index 8f3875ae63c..a0656ceb4d9 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JDK9Wrappers.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/JDK9Wrappers.java @@ -25,6 +25,7 @@ package com.sun.tools.javac.util; +import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.file.Path; @@ -367,4 +368,41 @@ public class JDK9Wrappers { } } } + + /** + * Helper class for new method in jdk.internal.jmod.JmodFile + */ + public static final class JmodFile { + public static final String JMOD_FILE_CLASSNAME = "jdk.internal.jmod.JmodFile"; + + public static void checkMagic(Path file) throws IOException { + try { + init(); + checkMagicMethod.invoke(null, file); + } catch (InvocationTargetException ex) { + if (ex.getCause() instanceof IOException) { + throw IOException.class.cast(ex.getCause()); + } + throw new Abort(ex); + } catch (IllegalAccessException | IllegalArgumentException | SecurityException ex) { + throw new Abort(ex); + } + } + + // ----------------------------------------------------------------------------------------- + + private static Class jmodFileClass = null; + private static Method checkMagicMethod = null; + + private static void init() { + if (jmodFileClass == null) { + try { + jmodFileClass = Class.forName(JMOD_FILE_CLASSNAME, false, null); + checkMagicMethod = jmodFileClass.getDeclaredMethod("checkMagic", Path.class); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { + throw new Abort(ex); + } + } + } + } } diff --git a/langtools/src/jdk.compiler/share/classes/module-info.java b/langtools/src/jdk.compiler/share/classes/module-info.java index be878af4f01..adbd78224c0 100644 --- a/langtools/src/jdk.compiler/share/classes/module-info.java +++ b/langtools/src/jdk.compiler/share/classes/module-info.java @@ -70,6 +70,9 @@ module jdk.compiler { uses com.sun.source.util.Plugin; uses com.sun.tools.javac.platform.PlatformProvider; + provides java.util.spi.ToolProvider + with com.sun.tools.javac.main.JavacToolProvider; + provides com.sun.tools.javac.platform.PlatformProvider with com.sun.tools.javac.platform.JDKPlatformProvider; diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java index d783fd35f05..e7c5385d937 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java @@ -368,7 +368,7 @@ public abstract class AbstractMemberWriter { * @param htmltree the content tree to which the comment will be added. */ protected void addComment(Element member, Content htmltree) { - if (!utils.getBody(member).isEmpty()) { + if (!utils.getFullBody(member).isEmpty()) { writer.addInlineComment(member, htmltree); } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java index d0d621df905..96b985ffa12 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java @@ -290,8 +290,8 @@ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter */ @Override public void addAnnotationTypeDescription(Content annotationInfoTree) { - if(!configuration.nocomment) { - if (!utils.getBody(annotationType).isEmpty()) { + if (!configuration.nocomment) { + if (!utils.getFullBody(annotationType).isEmpty()) { addInlineComment(annotationType, annotationInfoTree); } } @@ -302,7 +302,7 @@ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter */ @Override public void addAnnotationTypeTagInfo(Content annotationInfoTree) { - if(!configuration.nocomment) { + if (!configuration.nocomment) { addTagsInfo(annotationType, annotationInfoTree); } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java index e812649f7cf..a5b95ff2731 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java @@ -353,7 +353,7 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite public void addClassDescription(Content classInfoTree) { if(!configuration.nocomment) { // generate documentation for the class. - if (!utils.getBody(typeElement).isEmpty()) { + if (!utils.getFullBody(typeElement).isEmpty()) { addInlineComment(typeElement, classInfoTree); } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java index 9a9c7a9d59a..c5a0d4ac2c0 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FieldWriterImpl.java @@ -146,7 +146,7 @@ public class FieldWriterImpl extends AbstractMemberWriter */ @Override public void addComments(VariableElement field, Content fieldTree) { - if (!utils.getBody(field).isEmpty()) { + if (!utils.getFullBody(field).isEmpty()) { writer.addInlineComment(field, fieldTree); } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index 96a5e887ed6..3467dd452e6 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -1704,7 +1704,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @param htmltree the documentation tree to which the inline comments will be added */ public void addInlineComment(Element element, Content htmltree) { - addCommentTags(element, utils.getBody(element), false, false, htmltree); + addCommentTags(element, utils.getFullBody(element), false, false, htmltree); } /** diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java index 5421c278411..5d6ab274f97 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlSerialFieldWriter.java @@ -159,7 +159,7 @@ public class HtmlSerialFieldWriter extends FieldWriterImpl * @param contentTree the tree to which the deprecated info will be added */ public void addMemberDescription(VariableElement field, Content contentTree) { - if (!utils.getBody(field).isEmpty()) { + if (!utils.getFullBody(field).isEmpty()) { writer.addInlineComment(field, contentTree); } List tags = utils.getBlockTags(field, DocTree.Kind.SERIAL); @@ -210,7 +210,7 @@ public class HtmlSerialFieldWriter extends FieldWriterImpl */ public boolean shouldPrintOverview(VariableElement field) { if (!configuration.nocomment) { - if(!utils.getBody(field).isEmpty() || + if(!utils.getFullBody(field).isEmpty() || writer.hasSerializationOverviewTags(field)) return true; } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java index 89abfce4ecb..7821ba22e75 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java @@ -172,7 +172,7 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter @Override public void addComments(TypeMirror holderType, ExecutableElement method, Content methodDocTree) { TypeElement holder = utils.asTypeElement(holderType); - if (!utils.getBody(method).isEmpty()) { + if (!utils.getFullBody(method).isEmpty()) { if (holder.equals(typeElement) || !(utils.isPublic(holder) || utils.isLinkable(holder))) { diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java index 5ff751d9f0e..2d8317780a3 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleIndexWriter.java @@ -182,7 +182,7 @@ public class ModuleIndexWriter extends AbstractModuleIndexWriter { @Override protected void addOverviewHeader(Content body) { addConfigurationTitle(body); - if (!utils.getBody(configuration.overviewElement).isEmpty()) { + if (!utils.getFullBody(configuration.overviewElement).isEmpty()) { HtmlTree subTitleDiv = new HtmlTree(HtmlTag.DIV); subTitleDiv.addStyle(HtmlStyle.subTitle); addSummaryComment(configuration.overviewElement, subTitleDiv); @@ -212,7 +212,7 @@ public class ModuleIndexWriter extends AbstractModuleIndexWriter { * be added */ protected void addOverviewComment(Content htmltree) { - if (!utils.getBody(configuration.overviewElement).isEmpty()) { + if (!utils.getFullBody(configuration.overviewElement).isEmpty()) { htmltree.addContent(getMarkerAnchor(SectionName.OVERVIEW_DESCRIPTION)); addInlineComment(configuration.overviewElement, htmltree); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java index 75ee6180efd..bb1e9038e26 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java @@ -484,7 +484,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW * {@inheritDoc} */ public void addModuleDescription(Content moduleContentTree) { - if (!utils.getBody(mdle).isEmpty()) { + if (!utils.getFullBody(mdle).isEmpty()) { Content tree = configuration.allowTag(HtmlTag.SECTION) ? HtmlTree.SECTION() : moduleContentTree; tree.addContent(HtmlConstants.START_OF_MODULE_DESCRIPTION); tree.addContent(getMarkerAnchor(SectionName.MODULE_DESCRIPTION)); @@ -528,7 +528,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW li.addContent(Contents.SPACE); Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); Content liNav = new HtmlTree(HtmlTag.LI); - liNav.addContent(!utils.getBody(mdle).isEmpty() && !configuration.nocomment + liNav.addContent(!utils.getFullBody(mdle).isEmpty() && !configuration.nocomment ? getHyperLink(SectionName.MODULE_DESCRIPTION, contents.navModuleDescription) : contents.navModuleDescription); addNavGap(liNav); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java index f6360804701..cf5f1da6fbf 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexWriter.java @@ -175,7 +175,7 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter { @Override protected void addOverviewHeader(Content body) { addConfigurationTitle(body); - if (!utils.getBody(configuration.overviewElement).isEmpty()) { + if (!utils.getFullBody(configuration.overviewElement).isEmpty()) { HtmlTree subTitleDiv = new HtmlTree(HtmlTag.DIV); subTitleDiv.addStyle(HtmlStyle.subTitle); addSummaryComment(configuration.overviewElement, subTitleDiv); @@ -205,7 +205,7 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter { * be added */ protected void addOverviewComment(Content htmltree) { - if (!utils.getBody(configuration.overviewElement).isEmpty()) { + if (!utils.getFullBody(configuration.overviewElement).isEmpty()) { htmltree.addContent(getMarkerAnchor(SectionName.OVERVIEW_DESCRIPTION)); addInlineComment(configuration.overviewElement, htmltree); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java index e787014a798..88632495d2d 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageWriterImpl.java @@ -143,19 +143,6 @@ public class PackageWriterImpl extends HtmlDocletWriter Content packageHead = new StringContent(heading); tHeading.addContent(packageHead); div.addContent(tHeading); - addDeprecationInfo(div); - if (!utils.getBody(packageElement).isEmpty() && !configuration.nocomment) { - HtmlTree docSummaryDiv = new HtmlTree(HtmlTag.DIV); - docSummaryDiv.addStyle(HtmlStyle.docSummary); - addSummaryComment(packageElement, docSummaryDiv); - div.addContent(docSummaryDiv); - Content space = Contents.SPACE; - Content descLink = getHyperLink(getDocLink( - SectionName.PACKAGE_DESCRIPTION), - contents.descriptionLabel, "", ""); - Content descPara = new HtmlTree(HtmlTag.P, contents.seeLabel, space, descLink); - div.addContent(descPara); - } if (configuration.allowTag(HtmlTag.MAIN)) { mainTree.addContent(div); } else { @@ -259,19 +246,9 @@ public class PackageWriterImpl extends HtmlDocletWriter @Override public void addPackageDescription(Content packageContentTree) { if (!utils.getBody(packageElement).isEmpty()) { - packageContentTree.addContent( - getMarkerAnchor(SectionName.PACKAGE_DESCRIPTION)); - Content h2Content = new StringContent( - configuration.getText("doclet.Package_Description", - packageElement.isUnnamed() ? "" : utils.getPackageName(packageElement))); - Content heading = HtmlTree.HEADING(HtmlConstants.PACKAGE_HEADING, true, h2Content); - if (configuration.allowTag(HtmlTag.SECTION)) { - sectionTree.addContent(heading); - addInlineComment(packageElement, sectionTree); - } else { - packageContentTree.addContent(heading); - addInlineComment(packageElement, packageContentTree); - } + Content tree = configuration.allowTag(HtmlTag.SECTION) ? sectionTree : packageContentTree; + addDeprecationInfo(tree); + addInlineComment(packageElement, tree); } } @@ -284,6 +261,9 @@ public class PackageWriterImpl extends HtmlDocletWriter ? sectionTree : packageContentTree; addTagsInfo(packageElement, htmlTree); + if (configuration.allowTag(HtmlTag.SECTION)) { + packageContentTree.addContent(sectionTree); + } } /** @@ -292,7 +272,6 @@ public class PackageWriterImpl extends HtmlDocletWriter @Override public void addPackageContent(Content contentTree, Content packageContentTree) { if (configuration.allowTag(HtmlTag.MAIN)) { - packageContentTree.addContent(sectionTree); mainTree.addContent(packageContentTree); contentTree.addContent(mainTree); } else { diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java index 7538fd6c57a..91b0e039471 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java @@ -147,7 +147,7 @@ public class PropertyWriterImpl extends AbstractMemberWriter @Override public void addComments(ExecutableElement property, Content propertyDocTree) { TypeElement holder = (TypeElement)property.getEnclosingElement(); - if (!utils.getBody(property).isEmpty()) { + if (!utils.getFullBody(property).isEmpty()) { if (holder.equals(typeElement) || (!utils.isPublic(holder) || utils.isLinkable(holder))) { writer.addInlineComment(property, propertyDocTree); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties index a56d6c006d1..a69ac46a45f 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties @@ -97,7 +97,6 @@ doclet.deprecated_enum_constants=deprecated enum constants doclet.deprecated_annotation_type_members=deprecated annotation type elements doclet.Generated_Docs_Untitled=Generated Documentation (Untitled) doclet.Other_Packages=Other Packages -doclet.Package_Description=Package {0} Description doclet.Description=Description doclet.Specified_By=Specified by: doclet.in_interface=in interface diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java index b4583e1599e..4d2a48e43a1 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java @@ -40,7 +40,6 @@ import jdk.javadoc.internal.doclets.toolkit.builders.AbstractBuilder; import jdk.javadoc.internal.doclets.toolkit.builders.BuilderFactory; import jdk.javadoc.internal.doclets.toolkit.util.ClassTree; import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException; -import jdk.javadoc.internal.doclets.toolkit.util.DocPaths; import jdk.javadoc.internal.doclets.toolkit.util.InternalException; import jdk.javadoc.internal.doclets.toolkit.util.PackageListWriter; import jdk.javadoc.internal.doclets.toolkit.util.ResourceIOException; @@ -112,8 +111,6 @@ public abstract class AbstractDoclet implements Doclet { return false; } - boolean dumpOnError = false; // set true to always show stack traces - try { startGeneration(docEnv); return true; @@ -128,16 +125,16 @@ public abstract class AbstractDoclet implements Doclet { messages.error("doclet.exception.write.file", e.fileName.getPath(), e.getCause()); } - dumpStack(dumpOnError, e); + dumpStack(configuration.dumpOnError, e); } catch (ResourceIOException e) { messages.error("doclet.exception.read.resource", e.resource.getPath(), e.getCause()); - dumpStack(dumpOnError, e); + dumpStack(configuration.dumpOnError, e); } catch (SimpleDocletException e) { configuration.reporter.print(ERROR, e.getMessage()); - dumpStack(dumpOnError, e); + dumpStack(configuration.dumpOnError, e); } catch (InternalException e) { configuration.reporter.print(ERROR, e.getMessage()); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/CommentUtils.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/CommentUtils.java index 4c7bc2d8548..ae11d9d41b3 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/CommentUtils.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/CommentUtils.java @@ -108,27 +108,22 @@ public class CommentUtils { Utils utils = config.utils; String klassName = utils.getSimpleName(utils.getEnclosingTypeElement(e)); - List fs = new ArrayList<>(); - fs.add(treeFactory.newTextTree(config.getText("doclet.enum_values_doc.firstsentence"))); - - List body = new ArrayList<>(); - body.add(treeFactory.newTextTree(config.getText("doclet.enum_values_doc.body", klassName))); + List fullBody = new ArrayList<>(); + fullBody.add(treeFactory.newTextTree(config.getText("doclet.enum_values_doc.fullbody", klassName))); List descriptions = new ArrayList<>(); descriptions.add(treeFactory.newTextTree(config.getText("doclet.enum_values_doc.return"))); List tags = new ArrayList<>(); tags.add(treeFactory.newReturnTree(descriptions)); - DocCommentTree docTree = treeFactory.newDocCommentTree(fs, body, tags); + DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, tags); dcTreesMap.put(e, new DocCommentDuo(null, docTree)); } public void setEnumValueOfTree(Configuration config, Element e) { - List fs = new ArrayList<>(); - fs.add(treeFactory.newTextTree(config.getText("doclet.enum_valueof_doc.firstsentence"))); - List body = new ArrayList<>(); - body.add(treeFactory.newTextTree(config.getText("doclet.enum_valueof_doc.body"))); + List fullBody = new ArrayList<>(); + fullBody.add(treeFactory.newTextTree(config.getText("doclet.enum_valueof_doc.fullbody"))); List tags = new ArrayList<>(); @@ -156,7 +151,7 @@ public class CommentUtils { ref = treeFactory.newReferenceTree("java.lang.NullPointerException"); tags.add(treeFactory.newThrowsTree(ref, throwsDescs)); - DocCommentTree docTree = treeFactory.newDocCommentTree(fs, body, tags); + DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, tags); dcTreesMap.put(e, new DocCommentDuo(null, docTree)); } @@ -190,11 +185,9 @@ public class CommentUtils { return new DocCommentDuo(treePath.getTreePath(), dcTree); } - public void setDocCommentTree(Element element, List firstSentence, - List bodyTags, List blockTags, Utils utils) { - DocCommentTree docTree = treeFactory.newDocCommentTree(firstSentence, - bodyTags, - blockTags); + public void setDocCommentTree(Element element, List fullBody, + List blockTags, Utils utils) { + DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, blockTags); dcTreesMap.put(element, new DocCommentDuo(null, docTree)); // There maybe an entry with the original comments usually null, // therefore remove that entry if it exists, and allow a new one diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java index 5fbf6d9d34d..f989263d139 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Configuration.java @@ -281,6 +281,8 @@ public abstract class Configuration { private String pkglistUrlForLinkOffline; + public boolean dumpOnError = false; + private List groups; public abstract Messages getMessages(); @@ -616,6 +618,13 @@ public abstract class Configuration { showversion = true; return true; } + }, + new Hidden(resources, "--dump-on-error") { + @Override + public boolean process(String opt, ListIterator args) { + dumpOnError = true; + return true; + } } }; Set set = new TreeSet<>(); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java index 36b8d909295..713fc028e7c 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java @@ -386,8 +386,8 @@ public class MemberSummaryBuilder extends AbstractMemberBuilder { CommentUtils cmtutils = configuration.cmtUtils; final boolean isSetter = isSetter(member); final boolean isGetter = isGetter(member); - List firstSentence = new ArrayList<>(); - List bodyTags = new ArrayList<>(); + + List fullBody = new ArrayList<>(); List blockTags = new ArrayList<>(); if (isGetter || isSetter) { //add "[GS]ets the value of the property PROPERTY_NAME." @@ -395,21 +395,21 @@ public class MemberSummaryBuilder extends AbstractMemberBuilder { String text = MessageFormat.format( configuration.getText("doclet.PropertySetterWithName"), utils.propertyName((ExecutableElement)member)); - firstSentence.addAll(cmtutils.makeFirstSentenceTree(text)); + fullBody.addAll(cmtutils.makeFirstSentenceTree(text)); } if (isGetter) { String text = MessageFormat.format( configuration.getText("doclet.PropertyGetterWithName"), utils.propertyName((ExecutableElement) member)); - firstSentence.addAll(cmtutils.makeFirstSentenceTree(text)); + fullBody.addAll(cmtutils.makeFirstSentenceTree(text)); } List propertyTags = utils.getBlockTags(property, "propertyDescription"); if (propertyTags.isEmpty()) { - List comment = utils.getBody(property); + List comment = utils.getFullBody(property); blockTags.addAll(cmtutils.makePropertyDescriptionTree(comment)); } } else { - firstSentence.addAll(utils.getBody(property)); + fullBody.addAll(utils.getFullBody(property)); } // copy certain tags @@ -452,7 +452,7 @@ public class MemberSummaryBuilder extends AbstractMemberBuilder { blockTags.add(cmtutils.makeSeeTree(sb.toString(), setter)); } } - cmtutils.setDocCommentTree(member, firstSentence, bodyTags, blockTags, utils); + cmtutils.setDocCommentTree(member, fullBody, blockTags, utils); } /** diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java index d31909d95b9..7511bdad07d 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java @@ -210,7 +210,7 @@ public class MethodBuilder extends AbstractMemberBuilder { public void buildMethodComments(XMLNode node, Content methodDocTree) { if (!configuration.nocomment) { ExecutableElement method = currentMethod; - if (utils.getBody(currentMethod).isEmpty()) { + if (utils.getFullBody(currentMethod).isEmpty()) { DocFinder.Output docs = DocFinder.search(configuration, new DocFinder.Input(utils, currentMethod)); if (docs.inlineTags != null && !docs.inlineTags.isEmpty()) diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml index 45a7e7fcd44..7a6c54d145a 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml @@ -42,6 +42,8 @@ + + @@ -50,8 +52,6 @@ - - diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties index aaf2392279a..fd7bc41235d 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties @@ -207,22 +207,21 @@ doclet.Value=Value doclet.0_and_1={0} and {1} #Documentation for Enums -doclet.enum_values_doc.firstsentence=\ -Returns an array containing the constants of this enum type, in\n\ -the order they are declared. -doclet.enum_values_doc.body=\ This method may be used to iterate\n\ +doclet.enum_values_doc.fullbody=\ + Returns an array containing the constants of this enum type, in\n\ + the order they are declared. This method may be used to iterate\n\ over the constants as follows:\n\
    \n\
      for ({0} c : {0}.values())\n\
          System.out.println(c);\n\
      
    + doclet.enum_values_doc.return=\ an array containing the constants of this enum type, in the order they are declared -doclet.enum_valueof_doc.firstsentence=\ -Returns the enum constant of this type with the specified name. -doclet.enum_valueof_doc.body=\n\ -The string must match exactly an identifier used to declare an\n\ +doclet.enum_valueof_doc.fullbody=\ + Returns the enum constant of this type with the specified name.\n\ + The string must match exactly an identifier used to declare an\n\ enum constant in this type. (Extraneous whitespace characters are \n\ not permitted.) diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletWriter.java index 652ea7e98c6..0b84c815254 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletWriter.java @@ -221,7 +221,7 @@ public abstract class TagletWriter { List taglets, TagletWriter writer, Content output) { Utils utils = writer.configuration().utils; tagletManager.checkTags(utils, element, utils.getBlockTags(element), false); - tagletManager.checkTags(utils, element, utils.getBody(element), true); + tagletManager.checkTags(utils, element, utils.getFullBody(element), true); for (Taglet taglet : taglets) { if (utils.isTypeElement(element) && taglet instanceof ParamTaglet) { //The type parameters are documented in a special section away diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFinder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFinder.java index f673cd69b0f..554663a8993 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFinder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFinder.java @@ -251,7 +251,7 @@ public class DocFinder { //We want overall documentation. output.inlineTags = input.isFirstSentence ? utils.getFirstSentenceTrees(input.element) - : utils.getBody(input.element); + : utils.getFullBody(input.element); output.holder = input.element; } else { input.taglet.inherit(input, output); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java index 80e9f0a6d8b..e23cf65983a 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java @@ -1453,7 +1453,7 @@ public class Utils { public void setEnumDocumentation(TypeElement elem) { for (Element e : getMethods(elem)) { ExecutableElement ee = (ExecutableElement)e; - if (!getBody(e).isEmpty()) // if already set skip it please + if (!getFullBody(e).isEmpty()) // ignore if already set continue; if (ee.getSimpleName().contentEquals("values") && ee.getParameters().isEmpty()) { configuration.cmtUtils.setEnumValuesTree(configuration, e); @@ -2939,12 +2939,18 @@ public class Utils { return dcTree; } + public List getFullBody(Element element) { + DocCommentTree docCommentTree = getDocCommentTree(element); + return (docCommentTree == null) + ? Collections.emptyList() + : docCommentTree.getFullBody(); + } + public List getBody(Element element) { DocCommentTree docCommentTree = getDocCommentTree(element); - if (docCommentTree == null) - return Collections.emptyList(); - - return docCommentTree.getFullBody(); + return (docCommentTree == null) + ? Collections.emptyList() + : docCommentTree.getFullBody(); } public List getDeprecatedTrees(Element element) { diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java index b1a5ba08e68..24ad4fd0740 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ElementsTable.java @@ -75,6 +75,7 @@ import jdk.javadoc.doclet.DocletEnvironment; import jdk.javadoc.doclet.DocletEnvironment.ModuleMode; import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; +import static jdk.javadoc.internal.tool.Main.Result.*; import static jdk.javadoc.internal.tool.JavadocTool.isValidClassName; /** @@ -158,6 +159,7 @@ public class ElementsTable { private final Location location; private final Modules modules; private final Map opts; + private final Messager messager; private final Map entries = new LinkedHashMap<>(); @@ -201,6 +203,8 @@ public class ElementsTable { this.fm = toolEnv.fileManager; this.modules = Modules.instance(context); this.opts = opts; + this.messager = Messager.instance0(context); + this.location = modules.multiModuleMode ? StandardLocation.MODULE_SOURCE_PATH : toolEnv.fileManager.hasLocation(StandardLocation.SOURCE_PATH) @@ -339,9 +343,9 @@ public class ElementsTable { * This is a terminal operation, thus no further modifications * are allowed to the specified data sets. * - * @throws IOException if an error occurs + * @throws ToolException if an error occurs */ - void analyze() throws IOException { + void analyze() throws ToolException { // compute the specified element, by expanding module dependencies computeSpecifiedModules(); @@ -354,7 +358,6 @@ public class ElementsTable { // compute the packages belonging to all the specified modules Set expandedModulePackages = computeModulePackages(); initializeIncludedSets(expandedModulePackages); - } ElementsTable classTrees(com.sun.tools.javac.util.List classTrees) { @@ -363,16 +366,17 @@ public class ElementsTable { } @SuppressWarnings("unchecked") - ElementsTable scanSpecifiedItems() throws IOException { + ElementsTable scanSpecifiedItems() throws ToolException { // scan modules specified on the command line List moduleNames = (List) opts.computeIfAbsent(ToolOption.MODULE, s -> Collections.EMPTY_LIST); List mlist = new ArrayList<>(); for (String m : moduleNames) { - Location moduleLoc = fm.getModuleLocation(location, m); + Location moduleLoc = getModuleLocation(location, m); if (moduleLoc == null) { - toolEnv.error("main.module_not_found", m); + String text = messager.getText("main.module_not_found", m); + throw new ToolException(CMDERR, text); } else { mlist.add(m); ModuleSymbol msym = syms.enterModule(names.fromString(m)); @@ -457,7 +461,7 @@ public class ElementsTable { } @SuppressWarnings("unchecked") - private void computeSubpackages() throws IOException { + private void computeSubpackages() throws ToolException { ((List) opts.computeIfAbsent(ToolOption.EXCLUDE, v -> Collections.EMPTY_LIST)) .stream() .map((packageName) -> new ModulePackage(packageName)) @@ -469,7 +473,14 @@ public class ElementsTable { for (ModulePackage modpkg : subPackages) { Location packageLocn = getLocation(modpkg); - for (JavaFileObject fo : fm.list(packageLocn, modpkg.packageName, sourceKinds, true)) { + Iterable list = null; + try { + list = fm.list(packageLocn, modpkg.packageName, sourceKinds, true); + } catch (IOException ioe) { + String text = messager.getText("main.file.manager.list", modpkg.packageName); + throw new ToolException(SYSERR, text, ioe); + } + for (JavaFileObject fo : list) { String binaryName = fm.inferBinaryName(packageLocn, fo); String pn = getPackageName(binaryName); String simpleName = getSimpleName(binaryName); @@ -554,22 +565,28 @@ public class ElementsTable { specifiedModuleElements = Collections.unmodifiableSet(result); } - private Set getAllModulePackages(ModuleElement mdle) throws IOException { + private Set getAllModulePackages(ModuleElement mdle) throws ToolException { Set result = new HashSet<>(); - ModuleSymbol msym = (ModuleSymbol)mdle; - Location msymloc = fm.getModuleLocation(location, msym.name.toString()); - for (JavaFileObject fo : fm.list(msymloc, "", sourceKinds, true)) { - if (fo.getName().endsWith("module-info.java")) - continue; - String binaryName = fm.inferBinaryName(msymloc, fo); - String pn = getPackageName(binaryName); - PackageSymbol psym = syms.enterPackage(msym, names.fromString(pn)); - result.add((PackageElement)psym); + ModuleSymbol msym = (ModuleSymbol) mdle; + Location msymloc = getModuleLocation(location, msym.name.toString()); + try { + for (JavaFileObject fo : fm.list(msymloc, "", sourceKinds, true)) { + if (fo.getName().endsWith("module-info.java")) + continue; + String binaryName = fm.inferBinaryName(msymloc, fo); + String pn = getPackageName(binaryName); + PackageSymbol psym = syms.enterPackage(msym, names.fromString(pn)); + result.add((PackageElement) psym); + } + + } catch (IOException ioe) { + String text = messager.getText("main.file.manager.list", msymloc.getName()); + throw new ToolException(SYSERR, text, ioe); } return result; } - private Set computeModulePackages() throws IOException { + private Set computeModulePackages() throws ToolException { final AccessKind accessValue = accessFilter.getAccessValue(ElementKind.PACKAGE); final boolean documentAllModulePackages = (accessValue == AccessKind.PACKAGE || accessValue == AccessKind.PRIVATE); @@ -662,10 +679,10 @@ public class ElementsTable { includedTypeElements = Collections.unmodifiableSet(iclasses); } - /** + /* * Computes the included packages and freezes the specified packages list. */ - private void computeSpecifiedPackages() throws IOException { + private void computeSpecifiedPackages() throws ToolException { computeSubpackages(); @@ -683,7 +700,7 @@ public class ElementsTable { if (pkg != null) { packlist.add(pkg); } else { - toolEnv.warning("main.package_not_found", modpkg.toString()); + messager.printWarningUsingKey("main.package_not_found", modpkg.toString()); } }); specifiedPackageElements = Collections.unmodifiableSet(packlist); @@ -693,7 +710,7 @@ public class ElementsTable { * Adds all classes as well as inner classes, to the specified * list. */ - private void computeSpecifiedTypes() { + private void computeSpecifiedTypes() throws ToolException { Set classes = new LinkedHashSet<>(); classDecList.stream().filter((def) -> (shouldDocument(def.sym))).forEach((def) -> { TypeElement te = (TypeElement) def.sym; @@ -701,24 +718,28 @@ public class ElementsTable { addAllClasses(classes, te, true); } }); - classArgList.forEach((className) -> { + for (String className : classArgList) { TypeElement te = toolEnv.loadClass(className); if (te == null) { - toolEnv.error("javadoc.class_not_found", className); + String text = messager.getText("javadoc.class_not_found", className); + throw new ToolException(CMDERR, text); } else { addAllClasses(classes, te, true); } - }); + } specifiedTypeElements = Collections.unmodifiableSet(classes); } private void addFilesForParser(Collection result, - Collection collection, boolean recurse) throws IOException { + Collection collection, + boolean recurse) throws ToolException { for (ModulePackage modpkg : collection) { toolEnv.notice("main.Loading_source_files_for_package", modpkg.toString()); List files = getFiles(modpkg, recurse); if (files.isEmpty()) { - toolEnv.error("main.no_source_files_for_package", modpkg.toString()); + String text = messager.getText("main.no_source_files_for_package", + modpkg.toString()); + throw new ToolException(CMDERR, text); } else { result.addAll(files); } @@ -732,7 +753,7 @@ public class ElementsTable { * @return a list of java file objects * @throws IOException if an error occurs */ - List getFilesToParse() throws IOException { + List getFilesToParse() throws ToolException { List result = new ArrayList<>(); addFilesForParser(result, cmdLinePackages, false); addFilesForParser(result, subPackages, true); @@ -744,9 +765,10 @@ public class ElementsTable { * * @param packageName the specified package * @return the set of file objects for the specified package - * @throws IOException if an error occurs while accessing the files + * @throws ToolException if an error occurs while accessing the files */ - private List getFiles(ModulePackage modpkg, boolean recurse) throws IOException { + private List getFiles(ModulePackage modpkg, + boolean recurse) throws ToolException { Entry e = getEntry(modpkg); // The files may have been found as a side effect of searching for subpackages if (e.files != null) { @@ -759,12 +781,18 @@ public class ElementsTable { return Collections.emptyList(); } String pname = modpkg.packageName; - for (JavaFileObject fo : fm.list(packageLocn, pname, sourceKinds, recurse)) { - String binaryName = fm.inferBinaryName(packageLocn, fo); - String simpleName = getSimpleName(binaryName); - if (isValidClassName(simpleName)) { - lb.append(fo); + + try { + for (JavaFileObject fo : fm.list(packageLocn, pname, sourceKinds, recurse)) { + String binaryName = fm.inferBinaryName(packageLocn, fo); + String simpleName = getSimpleName(binaryName); + if (isValidClassName(simpleName)) { + lb.append(fo); + } } + } catch (IOException ioe) { + String text = messager.getText("main.file.manager.list", pname); + throw new ToolException(SYSERR, text, ioe); } return lb.toList(); @@ -781,20 +809,30 @@ public class ElementsTable { return null; } - private Location getLocation(ModulePackage modpkg) throws IOException { + private Location getLocation(ModulePackage modpkg) throws ToolException { if (location != StandardLocation.MODULE_SOURCE_PATH) { return location; } if (modpkg.hasModule()) { - return fm.getModuleLocation(location, modpkg.moduleName); + return getModuleLocation(location, modpkg.moduleName); } // TODO: handle invalid results better. ModuleSymbol msym = findModuleOfPackageName(modpkg.packageName); if (msym == null) { return null; } - return fm.getModuleLocation(location, msym.name.toString()); + return getModuleLocation(location, msym.name.toString()); + } + + private Location getModuleLocation(Location location, String msymName) + throws ToolException { + try { + return fm.getModuleLocation(location, msymName); + } catch (IOException ioe) { + String text = messager.getText("main.doclet_could_not_get_location", msymName); + throw new ToolException(ERROR, text, ioe); + } } private Entry getEntry(String name) { @@ -841,7 +879,10 @@ public class ElementsTable { } } } catch (CompletionFailure e) { - // quietly ignore completion failures + if (e.getMessage() != null) + messager.printWarning(e.getMessage()); + else + messager.printWarningUsingKey("main.unexpected.exception", e); } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/IllegalOptionValue.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/IllegalOptionValue.java new file mode 100644 index 00000000000..1c32618c1a6 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/IllegalOptionValue.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.tool; + +import static jdk.javadoc.internal.tool.Main.Result.CMDERR; + +/** + * Provides a mechanism for the javadoc tool to indicate an option + * decoding issue, arising from command line error. + * + *

    This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ + +class IllegalOptionValue extends OptionException { + + private static final long serialVersionUID = 0; + + /** + * Constructs an object containing a runnable and a message. + * @param method a method to display suitable usage text + * @param message the detailed message + */ + IllegalOptionValue(Runnable method, String message) { + super(CMDERR, method, message); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java index a5597bf40d9..bee71775e43 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java @@ -27,7 +27,6 @@ package jdk.javadoc.internal.tool; import java.io.File; -import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashSet; @@ -51,6 +50,8 @@ import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Position; import jdk.javadoc.doclet.DocletEnvironment; +import static jdk.javadoc.internal.tool.Main.Result.*; + /** * This class could be the main entry point for Javadoc when Javadoc is used as a * component in a larger software system. It provides operations to @@ -120,9 +121,10 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { } } - public DocletEnvironment getEnvironment(Map jdtoolOpts, - List javaNames, - Iterable fileObjects) throws IOException { + public DocletEnvironment getEnvironment(Map jdtoolOpts, + List javaNames, + Iterable fileObjects) throws ToolException { toolEnv = ToolEnvironment.instance(context); toolEnv.initialize(jdtoolOpts); ElementsTable etable = new ElementsTable(context, jdtoolOpts); @@ -133,10 +135,12 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { if (etable.xclasses) { // If -Xclasses is set, the args should be a list of class names for (String arg: javaNames) { - if (!isValidPackageName(arg)) // checks - toolEnv.error("main.illegal_class_name", arg); + if (!isValidPackageName(arg)) { // checks + String text = messager.getText("main.illegal_class_name", arg); + throw new ToolException(CMDERR, text); + } } - if (messager.nerrors() != 0) { + if (messager.hasErrors()) { return null; } etable.setClassArgList(javaNames); @@ -157,19 +161,23 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { for (String arg: javaNames) { if (fm != null && arg.endsWith(".java") && new File(arg).exists()) { if (new File(arg).getName().equals("module-info.java")) { - toolEnv.warning("main.file_ignored", arg); + messager.printWarningUsingKey("main.file_ignored", arg); } else { parse(fm.getJavaFileObjects(arg), classTrees, true); } } else if (isValidPackageName(arg)) { packageNames.add(arg); } else if (arg.endsWith(".java")) { - if (fm == null) - throw new IllegalArgumentException(); - else - toolEnv.error("main.file_not_found", arg); + if (fm == null) { + String text = messager.getText("main.assertion.error", "fm == null"); + throw new ToolException(ABNORMAL, text); + } else { + String text = messager.getText("main.file_not_found", arg); + throw new ToolException(ERROR, text); + } } else { - toolEnv.error("main.illegal_package_name", arg); + String text = messager.getText("main.illegal_package_name", arg); + throw new ToolException(CMDERR, text); } } @@ -185,7 +193,7 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { parse(etable.getFilesToParse(), packageTrees, false); modules.enter(packageTrees.toList(), null); - if (messager.nerrors() != 0) { + if (messager.hasErrors()) { return null; } @@ -197,10 +205,19 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { enterDone = true; etable.analyze(); } catch (CompletionFailure cf) { - toolEnv.printError(cf.getMessage()); - } catch (Abort ex) {} + throw new ToolException(ABNORMAL, cf.getMessage(), cf); + } catch (Abort abort) { + if (messager.hasErrors()) { + // presumably a message has been emitted, keep silent + throw new ToolException(ABNORMAL, "", abort); + } else { + String text = messager.getText("main.internal.error"); + Throwable t = abort.getCause() == null ? abort : abort.getCause(); + throw new ToolException(ABNORMAL, text, t); + } + } - if (messager.nerrors() != 0) + if (messager.hasErrors()) return null; toolEnv.docEnv = new DocEnvImpl(toolEnv, etable); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocToolProvider.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocToolProvider.java new file mode 100644 index 00000000000..ead16f7de42 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocToolProvider.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.tool; + +import java.io.PrintWriter; +import java.util.spi.ToolProvider; + +/** + * An implementation of the {@link java.util.spi.ToolProvider ToolProvider} SPI, + * providing access to JDK documentation tool, javadoc. + * + * @since 9 + */ +// This is currently a stand-alone top-level class so that it can easily be excluded +// from interims builds of javadoc, used while building JDK. +public class JavadocToolProvider implements ToolProvider { + public String name() { + return "javadoc"; + } + + public int run(PrintWriter out, PrintWriter err, String... args) { + return Main.execute(args, out, err); + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Main.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Main.java index a8725f1fb9d..b91dcfefd67 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Main.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Main.java @@ -60,18 +60,61 @@ public class Main { */ public static int execute(String... args) { Start jdoc = new Start(); - return jdoc.begin(args); + return jdoc.begin(args).exitCode; } /** * Programmatic interface. * - * @param writer PrintWriter to receive notice messages. + * @param writer a stream for all output * @param args The command line parameters. * @return The return code. */ public static int execute(String[] args, PrintWriter writer) { - Start jdoc = new Start(writer); - return jdoc.begin(args); + Start jdoc = new Start(writer, writer); + return jdoc.begin(args).exitCode; + } + + /** + * Programmatic interface. + * + * @param outWriter a stream for expected output + * @param errWriter a stream for diagnostic output + * @param args The command line parameters. + * @return The return code. + */ + public static int execute(String[] args, PrintWriter outWriter, PrintWriter errWriter) { + Start jdoc = new Start(outWriter, errWriter); + return jdoc.begin(args).exitCode; + } + + public static enum Result { + /** completed with no errors */ + OK(0), + /** Completed with reported errors */ + ERROR(1), + /** Bad command-line arguments */ + CMDERR(2), + /** System error or resource exhaustion */ + SYSERR(3), + /** Terminated abnormally */ + ABNORMAL(4); + + private static final long serialVersionUID = 1L; + + Result(int exitCode) { + this.exitCode = exitCode; + } + + public boolean isOK() { + return (exitCode == 0); + } + + public final int exitCode; + + @Override + public String toString() { + return name() + '(' + exitCode + ')'; + } } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Messager.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Messager.java index 37829952b91..478366d78e3 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Messager.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Messager.java @@ -48,10 +48,8 @@ import com.sun.tools.javac.util.Log; /** * Utility for integrating with javadoc tools and for localization. - * Handle Resources. Access to error and warning counts. - * Message formatting. - *
    - * Also provides implementation for DocErrorReporter. + * Handle resources, access to error and warning counts and + * message formatting. * *

    This is NOT part of any supported API. * If you write code that depends on this, you do so at your own risk. @@ -139,10 +137,6 @@ public class Messager extends Log implements Reporter { } } - public static class ExitJavadoc extends Error { - private static final long serialVersionUID = 0; - } - final String programName; private Locale locale; @@ -165,8 +159,8 @@ public class Messager extends Log implements Reporter { /** * Constructor * @param programName Name of the program (for error messages). - * @param stdOut Stream for notices etc. - * @param stdErr Stream for errors and warnings + * @param outWriter Stream for notices etc. + * @param errWriter Stream for errors and warnings */ @SuppressWarnings("deprecation") public Messager(Context context, String programName, PrintWriter outWriter, PrintWriter errWriter) { @@ -240,7 +234,7 @@ public class Messager extends Log implements Reporter { report(DiagnosticType.ERROR, prefix, msg); return; } - incrementErrorCount(prefix, msg); + printError(prefix, msg); } public void printError(Element e, String msg) { @@ -249,10 +243,15 @@ public class Messager extends Log implements Reporter { report(DiagnosticType.ERROR, prefix, msg); return; } - incrementErrorCount(prefix, msg); + printError(prefix, msg); } - private void incrementErrorCount(String prefix, String msg) { + public void printErrorUsingKey(String key, Object... args) { + printError((Element)null, getText(key, args)); + } + + // print the error and increment count + private void printError(String prefix, String msg) { if (nerrors < MaxErrors) { PrintWriter errWriter = getWriter(WriterKind.ERROR); printRawLines(errWriter, prefix + ": " + getText("javadoc.error") + " - " + msg); @@ -272,13 +271,21 @@ public class Messager extends Log implements Reporter { printWarning((DocTreePath)null, msg); } + public void printWarningUsingKey(String key, Object... args) { + printWarning((Element)null, getText(key, args)); + } + + public void printWarning(Element e, String key, Object... args) { + printWarning(getText(key, args)); + } + public void printWarning(DocTreePath path, String msg) { String prefix = getDiagSource(path); if (diagListener != null) { report(DiagnosticType.WARNING, prefix, msg); return; } - incrementWarningCount(prefix, msg); + printWarning(prefix, msg); } public void printWarning(Element e, String msg) { @@ -287,10 +294,11 @@ public class Messager extends Log implements Reporter { report(DiagnosticType.WARNING, prefix, msg); return; } - incrementWarningCount(prefix, msg); + printWarning(prefix, msg); } - private void incrementWarningCount(String prefix, String msg) { + // print the warning and increment count + private void printWarning(String prefix, String msg) { if (nwarnings < MaxWarnings) { PrintWriter warnWriter = getWriter(WriterKind.WARNING); printRawLines(warnWriter, prefix + ": " + getText("javadoc.warning") + " - " + msg); @@ -341,50 +349,6 @@ public class Messager extends Log implements Reporter { noticeWriter.flush(); } - /** - * Print error message, increment error count. - * - * @param key selects message from resource - */ - public void error(Element e, String key, Object... args) { - printError(e, getText(key, args)); - } - - /** - * Print error message, increment error count. - * - * @param key selects message from resource - */ - public void error(DocTreePath path, String key, Object... args) { - printError(path, getText(key, args)); - } - - public void error(String key, Object... args) { - printError((Element)null, getText(key, args)); - } - - public void warning(String key, Object... args) { - printWarning((Element)null, getText(key, args)); - } - - /** - * Print warning message, increment warning count. - * - * @param key selects message from resource - */ - public void warning(Element e, String key, Object... args) { - printWarning(e, getText(key, args)); - } - - /** - * Print warning message, increment warning count. - * - * @param key selects message from resource - */ - public void warning(DocTreePath path, String key, Object... args) { - printWarning(path, getText(key, args)); - } - /** * Print a message. * @@ -395,21 +359,23 @@ public class Messager extends Log implements Reporter { } /** - * Return total number of errors, including those recorded - * in the compilation log. + * Returns true if errors have been recorded. */ - public int nerrors() { return nerrors; } + public boolean hasErrors() { + return nerrors != 0; + } /** - * Return total number of warnings, including those recorded - * in the compilation log. + * Returns true if warnings have been recorded. */ - public int nwarnings() { return nwarnings; } + public boolean hasWarnings() { + return nwarnings != 0; + } /** * Print exit message. */ - public void exitNotice() { + public void printErrorWarningCounts() { if (nerrors > 0) { notice((nerrors > 1) ? "main.errors" : "main.error", "" + nerrors); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/OptionException.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/OptionException.java new file mode 100644 index 00000000000..3a9bf89299b --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/OptionException.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.tool; + +import jdk.javadoc.internal.tool.Main.Result; + +/** + * Provides a general mechanism for the javadoc tool to indicate an option + * decoding issue. + * + *

    This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ + +class OptionException extends Exception { + + private static final long serialVersionUID = 0; + + public final Result result; + public final String message; + public final Runnable m; + + /** + * Constructs an object with a result, runnable and a message + * to be printed out by the catcher. The runnable can be invoked + * by the catcher to display the usage text. + * @param result the exit code + * @param method the method to invoke + * @param message the detailed message + */ + public OptionException(Result result, Runnable method, String message) { + this.result = result; + this.m = method; + this.message = message; + if (result == null || result.isOK() || method == null || message == null) { + throw new AssertionError("result == null || result.isOK() || " + + "method == null || message == null"); + } + } + + /** + * Constructs an object with a result and a runnable. + * The runnable can be invoked by the catcher to display the usage text. + * @param result the exit code + * @param method the method to invoke + */ + public OptionException(Result result, Runnable method) { + this.result = result; + this.m = method; + this.message = null; + if (result == null || method == null) { + throw new AssertionError("result == null || method == null"); + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java index 431826c5e94..c5b94f3500b 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java @@ -26,7 +26,6 @@ package jdk.javadoc.internal.tool; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Path; @@ -65,11 +64,12 @@ import com.sun.tools.javac.util.Options; import jdk.javadoc.doclet.Doclet; import jdk.javadoc.doclet.Doclet.Option; import jdk.javadoc.doclet.DocletEnvironment; -import jdk.javadoc.internal.doclets.toolkit.Resources; +import jdk.javadoc.internal.tool.Main.Result; import static javax.tools.DocumentationTool.Location.*; import static com.sun.tools.javac.main.Option.*; +import static jdk.javadoc.internal.tool.Main.Result.*; /** * Main program of Javadoc. @@ -119,20 +119,21 @@ public class Start extends ToolOption.Helper { private JavaFileManager fileManager; Start() { - this(null, null, null, null, null); + this(null, null, null, null, null, null); } - Start(PrintWriter writer) { - this(null, null, writer, null, null); + Start(PrintWriter outWriter, PrintWriter errWriter) { + this(null, null, outWriter, errWriter, null, null); } - Start(Context context, String programName, PrintWriter writer, + Start(Context context, String programName, + PrintWriter outWriter, PrintWriter errWriter, String docletName, ClassLoader classLoader) { this.context = context == null ? new Context() : context; String pname = programName == null ? ProgramName : programName; - this.messager = writer == null + this.messager = (outWriter == null && errWriter == null) ? new Messager(this.context, pname) - : new Messager(this.context, pname, writer, writer); + : new Messager(this.context, pname, outWriter, errWriter); this.docletName = docletName; this.classLoader = classLoader; this.docletClass = null; @@ -169,41 +170,28 @@ public class Start extends ToolOption.Helper { */ @Override void usage() { - usage(true); - } - - void usage(boolean exit) { - usage("main.usage", "-help", "main.usage.foot"); - - if (exit) - throw new Messager.ExitJavadoc(); + usage("main.usage", OptionKind.STANDARD, "main.usage.foot"); } @Override void Xusage() { - Xusage(true); + usage("main.Xusage", OptionKind.EXTENDED, "main.Xusage.foot"); } - void Xusage(boolean exit) { - usage("main.Xusage", "-X", "main.Xusage.foot"); - - if (exit) - throw new Messager.ExitJavadoc(); - } - - private void usage(String header, String option, String footer) { - messager.notice(header); - showToolOptions(option.equals("-X") ? OptionKind.EXTENDED : OptionKind.STANDARD); + private void usage(String headerKey, OptionKind kind, String footerKey) { + messager.notice(headerKey); + showToolOptions(kind); // let doclet print usage information if (docletClass != null) { String name = doclet.getName(); messager.notice("main.doclet.usage.header", name); - showDocletOptions(option.equals("-X") ? Option.Kind.EXTENDED : Option.Kind.STANDARD); + showDocletOptions(kind == OptionKind.EXTENDED + ? Option.Kind.EXTENDED + : Option.Kind.STANDARD); } - - if (footer != null) - messager.notice(footer); + if (footerKey != null) + messager.notice(footerKey); } void showToolOptions(OptionKind kind) { @@ -325,25 +313,23 @@ public class Start extends ToolOption.Helper { * of class loader creation, needed to detect the doclet/taglet class variants. */ @SuppressWarnings("deprecation") - int begin(String... argv) { + Result begin(String... argv) { // Preprocess @file arguments try { argv = CommandLine.parse(argv); - } catch (FileNotFoundException e) { - messager.error("main.cant.read", e.getMessage()); - throw new Messager.ExitJavadoc(); } catch (IOException e) { - e.printStackTrace(System.err); - throw new Messager.ExitJavadoc(); + error("main.cant.read", e.getMessage()); + return ERROR; } if (argv.length > 0 && "-Xold".equals(argv[0])) { - messager.warning("main.legacy_api"); + warn("main.legacy_api"); String[] nargv = Arrays.copyOfRange(argv, 1, argv.length); - return com.sun.tools.javadoc.Main.execute(nargv); + return com.sun.tools.javadoc.Main.execute(nargv) == 0 + ? OK + : ERROR; } - boolean ok = begin(Arrays.asList(argv), Collections. emptySet()); - return ok ? 0 : 1; + return begin(Arrays.asList(argv), Collections. emptySet()); } // Called by 199 API. @@ -355,11 +341,11 @@ public class Start extends ToolOption.Helper { for (String opt: options) opts.add(opt); - return begin(opts, fileObjects); + return begin(opts, fileObjects).isOK(); } @SuppressWarnings("deprecation") - private boolean begin(List options, Iterable fileObjects) { + private Result begin(List options, Iterable fileObjects) { fileManager = context.get(JavaFileManager.class); if (fileManager == null) { JavacFileManager.preRegister(context); @@ -368,8 +354,28 @@ public class Start extends ToolOption.Helper { ((BaseFileManager) fileManager).autoClose = true; } } + // locale, doclet and maybe taglet, needs to be determined first - docletClass = preProcess(fileManager, options); + try { + docletClass = preprocess(fileManager, options); + } catch (ToolException te) { + if (!te.result.isOK()) { + if (te.message != null) { + messager.printError(te.message); + } + Throwable t = te.getCause(); + dumpStack(t == null ? te : t); + } + return te.result; + } catch (OptionException oe) { + if (oe.message != null) { + messager.printError(oe.message); + } + oe.m.run(); + Throwable t = oe.getCause(); + dumpStack(t == null ? oe : t); + return oe.result; + } if (jdk.javadoc.doclet.Doclet.class.isAssignableFrom(docletClass)) { // no need to dispatch to old, safe to init now initMessager(); @@ -378,43 +384,62 @@ public class Start extends ToolOption.Helper { Object o = docletClass.getConstructor().newInstance(); doclet = (Doclet) o; } catch (ReflectiveOperationException exc) { - exc.printStackTrace(); - if (!apiMode) { - error("main.could_not_instantiate_class", docletClass); - throw new Messager.ExitJavadoc(); + if (apiMode) { + throw new ClientCodeException(exc); } - throw new ClientCodeException(exc); + error("main.could_not_instantiate_class", docletClass); + return ERROR; } } else { - if (this.apiMode) { + if (apiMode) { com.sun.tools.javadoc.main.Start ostart = new com.sun.tools.javadoc.main.Start(context); - return ostart.begin(docletClass, options, fileObjects); + return ostart.begin(docletClass, options, fileObjects) + ? OK + : ERROR; } warn("main.legacy_api"); String[] array = options.toArray(new String[options.size()]); - return com.sun.tools.javadoc.Main.execute(array) == 0; + return com.sun.tools.javadoc.Main.execute(array) == 0 + ? OK + : ERROR; } - boolean failed = false; + Result result = OK; try { - failed = !parseAndExecute(options, fileObjects); - } catch (Messager.ExitJavadoc exc) { - // ignore, we just exit this way + result = parseAndExecute(options, fileObjects) + ? OK + : ERROR; + } catch (OptionException toe) { + if (toe.message != null) + messager.printError(toe.message); + + toe.m.run(); + Throwable t = toe.getCause(); + dumpStack(t == null ? toe : t); + return toe.result; + } catch (ToolException exc) { + if (exc.message != null) { + messager.printError(exc.message); + } + Throwable t = exc.getCause(); + if (result == ABNORMAL) { + reportInternalError(t == null ? exc : t); + } else { + dumpStack(t == null ? exc : t); + } + return exc.result; } catch (OutOfMemoryError ee) { - messager.error("main.out.of.memory"); - failed = true; + error("main.out.of.memory"); + result = SYSERR; + dumpStack(ee); } catch (ClientCodeException e) { // simply rethrow these exceptions, to be caught and handled by JavadocTaskImpl throw e; - } catch (Error ee) { - ee.printStackTrace(System.err); - messager.error("main.fatal.error"); - failed = true; - } catch (Exception ee) { - ee.printStackTrace(System.err); - messager.error("main.fatal.exception"); - failed = true; + } catch (Error | Exception ee) { + error("main.fatal.error", ee); + reportInternalError(ee); + result = ABNORMAL; } finally { if (fileManager != null && fileManager instanceof BaseFileManager @@ -423,17 +448,34 @@ public class Start extends ToolOption.Helper { fileManager.close(); } catch (IOException ignore) {} } - boolean haveErrorWarnings = messager.nerrors() > 0 || - (rejectWarnings && messager.nwarnings() > 0); - if (failed && !haveErrorWarnings) { + boolean haveErrorWarnings = messager.hasErrors() + || (rejectWarnings && messager.hasWarnings()); + if (!result.isOK() && !haveErrorWarnings) { // the doclet failed, but nothing reported, flag it!. - messager.error("main.unknown.error"); + error("main.unknown.error"); } - failed |= haveErrorWarnings; - messager.exitNotice(); + if (haveErrorWarnings && result.isOK()) { + result = ERROR; + } + messager.printErrorWarningCounts(); messager.flush(); } - return !failed; + return result; + } + + private void reportInternalError(Throwable t) { + messager.printErrorUsingKey("doclet.internal.report.bug"); + dumpStack(true, t); + } + + private void dumpStack(Throwable t) { + dumpStack(false, t); + } + + private void dumpStack(boolean enabled, Throwable t) { + if (t != null && (enabled || dumpOnError)) { + t.printStackTrace(System.err); + } } /** @@ -441,7 +483,7 @@ public class Start extends ToolOption.Helper { */ @SuppressWarnings("unchecked") private boolean parseAndExecute(List argList, - Iterable fileObjects) throws IOException { + Iterable fileObjects) throws ToolException, OptionException { long tm = System.currentTimeMillis(); List javaNames = new ArrayList<>(); @@ -462,17 +504,21 @@ public class Start extends ToolOption.Helper { if (platformString != null) { if (compOpts.isSet("-source")) { - usageError("main.release.bootclasspath.conflict", "-source"); + String text = messager.getText("main.release.bootclasspath.conflict", "-source"); + throw new ToolException(CMDERR, text); } if (fileManagerOpts.containsKey(BOOT_CLASS_PATH)) { - usageError("main.release.bootclasspath.conflict", BOOT_CLASS_PATH.getPrimaryName()); + String text = messager.getText("main.release.bootclasspath.conflict", + BOOT_CLASS_PATH.getPrimaryName()); + throw new ToolException(CMDERR, text); } PlatformDescription platformDescription = PlatformUtils.lookupPlatformDescription(platformString); if (platformDescription == null) { - usageError("main.unsupported.release.version", platformString); + String text = messager.getText("main.unsupported.release.version", platformString); + throw new IllegalArgumentException(text); } compOpts.put(SOURCE, platformDescription.getSourceVersion()); @@ -484,10 +530,15 @@ public class Start extends ToolOption.Helper { if (platformCP != null) { if (fileManager instanceof StandardJavaFileManager) { StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager; - - sfm.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, platformCP); + try { + sfm.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, platformCP); + } catch (IOException ioe) { + throw new ToolException(SYSERR, ioe.getMessage(), ioe); + } } else { - usageError("main.release.not.standard.file.manager", platformString); + String text = messager.getText("main.release.not.standard.file.manager", + platformString); + throw new ToolException(ABNORMAL, text); } } } @@ -501,7 +552,8 @@ public class Start extends ToolOption.Helper { s -> Collections.EMPTY_LIST); if (subpkgs.isEmpty()) { if (javaNames.isEmpty() && isEmpty(fileObjects)) { - usageError("main.No_modules_packages_or_classes_specified"); + String text = messager.getText("main.No_modules_packages_or_classes_specified"); + throw new ToolException(CMDERR, text); } } } @@ -534,7 +586,8 @@ public class Start extends ToolOption.Helper { } Set docletOptions = null; - int handleDocletOptions(int idx, List args, boolean isToolOption) { + int handleDocletOptions(int idx, List args, boolean isToolOption) + throws OptionException { if (docletOptions == null) { docletOptions = doclet.getSupportedOptions(); } @@ -548,24 +601,25 @@ public class Start extends ToolOption.Helper { argBase = arg; argVal = null; } - + String text = null; for (Doclet.Option opt : docletOptions) { if (opt.matches(argBase)) { if (argVal != null) { switch (opt.getArgumentCount()) { case 0: - usageError("main.unnecessary_arg_provided", argBase); - break; + text = messager.getText("main.unnecessary_arg_provided", argBase); + throw new OptionException(ERROR, this::usage, text); case 1: opt.process(arg, Arrays.asList(argVal).listIterator()); break; default: - usageError("main.only_one_argument_with_equals", argBase); - break; + text = messager.getText("main.only_one_argument_with_equals", argBase); + throw new OptionException(ERROR, this::usage, text); } } else { if (args.size() - idx -1 < opt.getArgumentCount()) { - usageError("main.requires_argument", arg); + text = messager.getText("main.requires_argument", arg); + throw new OptionException(ERROR, this::usage, text); } opt.process(arg, args.listIterator(idx + 1)); idx += opt.getArgumentCount(); @@ -574,12 +628,15 @@ public class Start extends ToolOption.Helper { } } // check if arg is accepted by the tool before emitting error - if (!isToolOption) - usageError("main.invalid_flag", arg); + if (!isToolOption) { + text = messager.getText("main.invalid_flag", arg); + throw new OptionException(ERROR, this::usage, text); + } return idx; } - private Class preProcess(JavaFileManager jfm, List argv) { + private Class preprocess(JavaFileManager jfm, + List argv) throws ToolException, OptionException { // doclet specifying arguments String userDocletPath = null; String userDocletName = null; @@ -592,19 +649,31 @@ public class Start extends ToolOption.Helper { // Step 1: loop through the args, set locale early on, if found. for (int i = 0 ; i < argv.size() ; i++) { String arg = argv.get(i); - if (arg.equals(ToolOption.LOCALE.primaryName)) { + if (arg.equals(ToolOption.DUMPONERROR.primaryName)) { + dumpOnError = true; + } else if (arg.equals(ToolOption.LOCALE.primaryName)) { checkOneArg(argv, i++); String lname = argv.get(i); locale = getLocale(lname); } else if (arg.equals(ToolOption.DOCLET.primaryName)) { checkOneArg(argv, i++); if (userDocletName != null) { - usageError("main.more_than_one_doclet_specified_0_and_1", + if (apiMode) { + throw new IllegalArgumentException("More than one doclet specified (" + + userDocletName + " and " + argv.get(i) + ")."); + } + String text = messager.getText("main.more_than_one_doclet_specified_0_and_1", userDocletName, argv.get(i)); + throw new ToolException(CMDERR, text); } if (docletName != null) { - usageError("main.more_than_one_doclet_specified_0_and_1", + if (apiMode) { + throw new IllegalArgumentException("More than one doclet specified (" + + docletName + " and " + argv.get(i) + ")."); + } + String text = messager.getText("main.more_than_one_doclet_specified_0_and_1", docletName, argv.get(i)); + throw new ToolException(CMDERR, text); } userDocletName = argv.get(i); } else if (arg.equals(ToolOption.DOCLETPATH.primaryName)) { @@ -643,23 +712,37 @@ public class Start extends ToolOption.Helper { try { ((StandardJavaFileManager)fileManager).setLocation(DOCLET_PATH, paths); } catch (IOException ioe) { - error("main.doclet_could_not_set_location", paths); - throw new Messager.ExitJavadoc(); + if (apiMode) { + throw new IllegalArgumentException("Could not set location for " + + userDocletPath, ioe); + } + String text = messager.getText("main.doclet_could_not_set_location", + userDocletPath); + throw new ToolException(CMDERR, text, ioe); } } cl = fileManager.getClassLoader(DOCLET_PATH); if (cl == null) { // despite doclet specified on cmdline no classloader found! - error("main.doclet_no_classloader_found", userDocletName); - throw new Messager.ExitJavadoc(); + if (apiMode) { + throw new IllegalArgumentException("Could not obtain classloader to load " + + userDocletPath); + } + String text = messager.getText("main.doclet_no_classloader_found", + userDocletName); + throw new ToolException(CMDERR, text); } } try { Class klass = cl.loadClass(userDocletName); return klass; } catch (ClassNotFoundException cnfe) { - error("main.doclet_class_not_found", userDocletName); - throw new Messager.ExitJavadoc(); + if (apiMode) { + throw new IllegalArgumentException("Cannot find doclet class " + userDocletName, + cnfe); + } + String text = messager.getText("main.doclet_class_not_found", userDocletName); + throw new ToolException(CMDERR, text, cnfe); } } @@ -668,8 +751,11 @@ public class Start extends ToolOption.Helper { try { return Class.forName(docletName, true, getClass().getClassLoader()); } catch (ClassNotFoundException cnfe) { - error("main.doclet_class_not_found", userDocletName); - throw new Messager.ExitJavadoc(); + if (apiMode) { + throw new IllegalArgumentException("Cannot find doclet class " + userDocletName); + } + String text = messager.getText("main.doclet_class_not_found", userDocletName); + throw new ToolException(CMDERR, text, cnfe); } } @@ -689,20 +775,20 @@ public class Start extends ToolOption.Helper { * nature to take its own course. */ @SuppressWarnings("deprecation") - private boolean hasOldTaglet(List tagletNames, List tagletPaths) { + private boolean hasOldTaglet(List tagletNames, List tagletPaths) throws ToolException { if (!fileManager.hasLocation(TAGLET_PATH)) { try { ((StandardJavaFileManager) fileManager).setLocation(TAGLET_PATH, tagletPaths); } catch (IOException ioe) { - error("main.doclet_could_not_set_location", tagletPaths); - throw new Messager.ExitJavadoc(); + String text = messager.getText("main.doclet_could_not_set_location", tagletPaths); + throw new ToolException(CMDERR, text, ioe); } } ClassLoader cl = fileManager.getClassLoader(TAGLET_PATH); if (cl == null) { // no classloader found! - error("main.doclet_no_classloader_found", tagletNames.get(0)); - throw new Messager.ExitJavadoc(); + String text = messager.getText("main.doclet_no_classloader_found", tagletNames.get(0)); + throw new ToolException(CMDERR, text); } for (String tagletName : tagletNames) { try { @@ -711,14 +797,15 @@ public class Start extends ToolOption.Helper { return true; } } catch (ClassNotFoundException cnfe) { - error("main.doclet_class_not_found", tagletName); - throw new Messager.ExitJavadoc(); + String text = messager.getText("main.doclet_class_not_found", tagletName); + throw new ToolException(CMDERR, text, cnfe); } } return false; } - private void parseArgs(List args, List javaNames) { + private void parseArgs(List args, List javaNames) throws ToolException, + OptionException { for (int i = 0 ; i < args.size() ; i++) { String arg = args.get(i); ToolOption o = ToolOption.get(arg); @@ -726,7 +813,6 @@ public class Start extends ToolOption.Helper { // handle a doclet argument that may be needed however // don't increment the index, and allow the tool to consume args handleDocletOptions(i, args, true); - if (o.hasArg) { if (arg.startsWith("--") && arg.contains("=")) { o.process(this, arg.substring(arg.indexOf('=') + 1)); @@ -762,24 +848,19 @@ public class Start extends ToolOption.Helper { * Check the one arg option. * Error and exit if one argument is not provided. */ - private void checkOneArg(List args, int index) { + private void checkOneArg(List args, int index) throws OptionException { if ((index + 1) >= args.size() || args.get(index + 1).startsWith("-d")) { - usageError("main.requires_argument", args.get(index)); + String text = messager.getText("main.requires_argument", args.get(index)); + throw new OptionException(CMDERR, this::usage, text); } } - @Override - void usageError(String key, Object... args) { - error(key, args); - usage(true); - } - void error(String key, Object... args) { - messager.error(key, args); + messager.printErrorUsingKey(key, args); } void warn(String key, Object... args) { - messager.warning(key, args); + messager.printWarningUsingKey(key, args); } /** @@ -787,7 +868,7 @@ public class Start extends ToolOption.Helper { * else return null and if locale option is not used * then return default locale. */ - private Locale getLocale(String localeName) { + private Locale getLocale(String localeName) throws ToolException { Locale userlocale = null; if (localeName == null || localeName.isEmpty()) { return Locale.getDefault(); @@ -803,8 +884,8 @@ public class Start extends ToolOption.Helper { if (seconduscore > 0) { if (seconduscore != firstuscore + 3 || localeName.length() <= seconduscore + 1) { - usageError("main.malformed_locale_name", localeName); - return null; + String text = messager.getText("main.malformed_locale_name", localeName); + throw new ToolException(CMDERR, text); } country = localeName.substring(firstuscore + 1, seconduscore); @@ -812,19 +893,19 @@ public class Start extends ToolOption.Helper { } else if (localeName.length() == firstuscore + 3) { country = localeName.substring(firstuscore + 1); } else { - usageError("main.malformed_locale_name", localeName); - return null; + String text = messager.getText("main.malformed_locale_name", localeName); + throw new ToolException(CMDERR, text); } } else if (firstuscore == -1 && localeName.length() == 2) { language = localeName; } else { - usageError("main.malformed_locale_name", localeName); - return null; + String text = messager.getText("main.malformed_locale_name", localeName); + throw new ToolException(CMDERR, text); } userlocale = searchLocale(language, country, variant); if (userlocale == null) { - usageError("main.illegal_locale_name", localeName); - return null; + String text = messager.getText("main.illegal_locale_name", localeName); + throw new ToolException(CMDERR, text); } else { return userlocale; } @@ -860,4 +941,9 @@ public class Start extends ToolOption.Helper { } }; } + + @Override + String getLocalizedMessage(String msg, Object... args) { + return messager.getText(msg, args); + } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java index 36ec03df351..3cdf46730a6 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolEnvironment.java @@ -87,7 +87,7 @@ public class ToolEnvironment { return instance; } - private final Messager messager; + final Messager messager; /** Predefined symbols known to the compiler. */ public final Symtab syms; @@ -204,182 +204,8 @@ public class ToolEnvironment { return path != null; } - //---------------- print forwarders ----------------// - - // ERRORS /** - * Print error message, increment error count. - * - * @param msg message to print. - */ - public void printError(String msg) { - messager.printError(msg); - } - -// /** -// * Print error message, increment error count. -// * -// * @param key selects message from resource -// */ -// public void error(Element element, String key) { -// if (element == null) -// messager.error(key); -// else -// messager.error(element, key); -// } -// -// public void error(String prefix, String key) { -// printError(prefix + ":" + messager.getText(key)); -// } -// -// /** -// * Print error message, increment error count. -// * -// * @param path the path to the source -// * @param key selects message from resource -// */ -// public void error(DocTreePath path, String key) { -// messager.error(path, key); -// } -// -// /** -// * Print error message, increment error count. -// * -// * @param path the path to the source -// * @param msg message to print. -// */ -// public void printError(DocTreePath path, String msg) { -// messager.printError(path, msg); -// } -// -// /** -// * Print error message, increment error count. -// * @param e the target element -// * @param msg message to print. -// */ -// public void printError(Element e, String msg) { -// messager.printError(e, msg); -// } - - /** - * Print error message, increment error count. - * @param key selects message from resource - * @param args replacement arguments - */ - public void error(String key, String... args) { - error(null, key, args); - } - - /** - * Print error message, increment error count. - * - * @param element the source element - * @param key selects message from resource - * @param args replacement arguments - */ - public void error(Element element, String key, String... args) { - if (element == null) - messager.error(key, (Object[]) args); - else - messager.error(element, key, (Object[]) args); - } - - // WARNINGS - -// /** -// * Print warning message, increment warning count. -// * -// * @param msg message to print. -// */ -// public void printWarning(String msg) { -// messager.printWarning(msg); -// } -// -// public void warning(String key) { -// warning((Element)null, key); -// } - - public void warning(String key, String... args) { - warning((Element)null, key, args); - } - -// /** -// * Print warning message, increment warning count. -// * -// * @param element the source element -// * @param key selects message from resource -// */ -// public void warning(Element element, String key) { -// if (element == null) -// messager.warning(key); -// else -// messager.warning(element, key); -// } -// -// /** -// * Print warning message, increment warning count. -// * -// * @param path the path to the source -// * @param msg message to print. -// */ -// public void printWarning(DocTreePath path, String msg) { -// messager.printWarning(path, msg); -// } -// -// /** -// * Print warning message, increment warning count. -// * -// * @param e the source element -// * @param msg message to print. -// */ -// public void printWarning(Element e, String msg) { -// messager.printWarning(e, msg); -// } - - /** - * Print warning message, increment warning count. - * - * @param e the source element - * @param key selects message from resource - * @param args the replace arguments - */ - public void warning(Element e, String key, String... args) { - if (e == null) - messager.warning(key, (Object[]) args); - else - messager.warning(e, key, (Object[]) args); - } - -// Note: no longer required -// /** -// * Print a message. -// * -// * @param msg message to print. -// */ -// public void printNotice(String msg) { -// if (quiet) { -// return; -// } -// messager.printNotice(msg); -// } - -// Note: no longer required -// /** -// * Print a message. -// * -// * @param e the source element -// * @param msg message to print. -// */ -// public void printNotice(Element e, String msg) { -// if (quiet) { -// return; -// } -// messager.printNotice(e, msg); -// } - - // NOTICES - /** - * Print a message. + * Print a notice, iff quiet is not specified. * * @param key selects message from resource */ @@ -390,22 +216,8 @@ public class ToolEnvironment { messager.notice(key); } -// Note: not used anymore -// /** -// * Print a message. -// * -// * @param path the path to the source -// * @param msg message to print. -// */ -// public void printNotice(DocTreePath path, String msg) { -// if (quiet) { -// return; -// } -// messager.printNotice(path, msg); -// } - /** - * Print a message. + * Print a notice, iff quiet is not specified. * * @param key selects message from resource * @param a1 first argument @@ -417,48 +229,6 @@ public class ToolEnvironment { messager.notice(key, a1); } -// Note: not used anymore -// /** -// * Print a message. -// * -// * @param key selects message from resource -// * @param a1 first argument -// * @param a2 second argument -// */ -// public void notice(String key, String a1, String a2) { -// if (quiet) { -// return; -// } -// messager.notice(key, a1, a2); -// } -// - -// Note: not used anymore -// /** -// * Print a message. -// * -// * @param key selects message from resource -// * @param a1 first argument -// * @param a2 second argument -// * @param a3 third argument -// */ -// public void notice(String key, String a1, String a2, String a3) { -// if (quiet) { -// return; -// } -// messager.notice(key, a1, a2, a3); -// } - - /** - * Exit, reporting errors and warnings. - */ - public void exit() { - // Messager should be replaced by a more general - // compilation environment. This can probably - // subsume DocEnv as well. - throw new Messager.ExitJavadoc(); - } - TreePath getTreePath(JCCompilationUnit tree) { TreePath p = treePaths.get(tree); if (p == null) diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolException.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolException.java new file mode 100644 index 00000000000..93b354aec10 --- /dev/null +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolException.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.javadoc.internal.tool; + +import jdk.javadoc.internal.tool.Main.Result; + +/** + * Provides a mechanism for the javadoc tool to terminate execution. + * This class is constructed with a result and an error message, + * that can be printed out before termination, a cause can also + * be wrapped to supply extended information about the exception. + * + *

    This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ + +class ToolException extends Exception { + + private static final long serialVersionUID = 0; + + final String message; + + final Result result; + + /** + * Constructs an object containing a result and a message to be + * printed out by the catcher. + * @param result the exit code + * @param message the detailed message + */ + ToolException(Result result, String message) { + this.message = message; + this.result = result; + if (result == null || result.isOK() || message == null) { + throw new AssertionError("result == null || result.isOK() || message == null"); + } + } + + /** + * Constructs an object containing a result, a messages and an underlying cause. + * @param result the exit code + * @param message the detailed message + * @param cause the underlying cause + */ + ToolException(Result result, String message, Throwable cause) { + super(cause); + this.message = message; + this.result = result; + if (result == null || message == null || cause == null || result.isOK()) { + throw new AssertionError("result == null || message == null" + + " || cause == null || result.isOK()"); + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java index 7a2325962ab..1949e684dd9 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/ToolOption.java @@ -40,6 +40,7 @@ import com.sun.tools.javac.main.OptionHelper; import com.sun.tools.javac.util.Options; import static com.sun.tools.javac.main.Option.OptionKind.*; +import static jdk.javadoc.internal.tool.Main.Result.*; /** * javadoc tool options. @@ -226,63 +227,63 @@ public enum ToolOption { PACKAGE("-package", STANDARD) { @Override - public void process(Helper helper) { + public void process(Helper helper) throws OptionException { helper.setSimpleFilter("package"); } }, PRIVATE("-private", STANDARD) { @Override - public void process(Helper helper) { + public void process(Helper helper) throws OptionException { helper.setSimpleFilter("private"); } }, PROTECTED("-protected", STANDARD) { @Override - public void process(Helper helper) { + public void process(Helper helper) throws OptionException { helper.setSimpleFilter("protected"); } }, PUBLIC("-public", STANDARD) { @Override - public void process(Helper helper) { + public void process(Helper helper) throws OptionException { helper.setSimpleFilter("public"); } }, SHOW_MEMBERS("--show-members", STANDARD, true) { @Override - public void process(Helper helper, String arg) { + public void process(Helper helper, String arg) throws OptionException { helper.setFilter(this, arg); } }, SHOW_TYPES("--show-types", STANDARD, true) { @Override - public void process(Helper helper, String arg) { + public void process(Helper helper, String arg) throws OptionException { helper.setFilter(this, arg); } }, SHOW_PACKAGES("--show-packages", STANDARD, true) { @Override - public void process(Helper helper, String arg) { + public void process(Helper helper, String arg) throws OptionException { helper.setShowPackageAccess(SHOW_PACKAGES, arg); } }, SHOW_MODULE_CONTENTS("--show-module-contents", STANDARD, true) { @Override - public void process(Helper helper, String arg) { + public void process(Helper helper, String arg) throws OptionException { helper.setShowModuleContents(SHOW_MODULE_CONTENTS, arg); } }, EXPAND_REQUIRES("--expand-requires", STANDARD, true) { @Override - public void process(Helper helper, String arg) { + public void process(Helper helper, String arg) throws OptionException { helper.setExpandRequires(EXPAND_REQUIRES, arg); } }, @@ -342,19 +343,26 @@ public enum ToolOption { } }, + DUMPONERROR("--dump-on-error", HIDDEN) { + @Override + public void process(Helper helper) { + helper.dumpOnError = true; + } + }, + // ----- help options ----- HELP("--help -help", STANDARD) { @Override - public void process(Helper helper) { - helper.usage(); + public void process(Helper helper) throws OptionException { + throw new OptionException(OK, helper::usage); } }, X("-X", STANDARD) { @Override - public void process(Helper helper) { - helper.Xusage(); + public void process(Helper helper) throws OptionException { + throw new OptionException(OK, helper::Xusage); } }, @@ -395,9 +403,9 @@ public enum ToolOption { this.hasSuffix = lastChar == ':' || lastChar == '='; } - void process(Helper helper, String arg) { } + void process(Helper helper, String arg) throws OptionException { } - void process(Helper helper) { } + void process(Helper helper) throws OptionException { } List getNames() { return names; @@ -451,6 +459,9 @@ public enum ToolOption { /** Javadoc tool options */ final Map jdtoolOpts = new EnumMap<>(ToolOption.class); + /** dump stack traces for debugging etc.*/ + boolean dumpOnError = false; + /** Set by -breakiterator. */ boolean breakiterator = false; @@ -470,7 +481,8 @@ public enum ToolOption { abstract void usage(); abstract void Xusage(); - abstract void usageError(String msg, Object... args); + abstract String getLocalizedMessage(String msg, Object... args); + abstract OptionHelper getOptionHelper(); @SuppressWarnings("unchecked") @@ -480,7 +492,7 @@ public enum ToolOption { jdtoolOpts.put(opt, list); } - void setExpandRequires(ToolOption opt, String arg) { + void setExpandRequires(ToolOption opt, String arg) throws OptionException { switch (arg) { case "public": jdtoolOpts.put(opt, AccessKind.PUBLIC); @@ -489,11 +501,12 @@ public enum ToolOption { jdtoolOpts.put(opt, AccessKind.PRIVATE); break; default: - usageError("main.illegal_option_value", arg); + String text = getLocalizedMessage("main.illegal_option_value", arg); + throw new IllegalOptionValue(this::usage, text); } } - void setShowModuleContents(ToolOption opt, String arg) { + void setShowModuleContents(ToolOption opt, String arg) throws OptionException { switch (arg) { case "api": jdtoolOpts.put(opt, AccessKind.PUBLIC); @@ -502,11 +515,12 @@ public enum ToolOption { jdtoolOpts.put(opt, AccessKind.PRIVATE); break; default: - usageError("main.illegal_option_value", arg); + String text = getLocalizedMessage("main.illegal_option_value", arg); + throw new IllegalOptionValue(this::usage, text); } } - void setShowPackageAccess(ToolOption opt, String arg) { + void setShowPackageAccess(ToolOption opt, String arg) throws OptionException { switch (arg) { case "exported": jdtoolOpts.put(opt, AccessKind.PUBLIC); @@ -515,16 +529,17 @@ public enum ToolOption { jdtoolOpts.put(opt, AccessKind.PRIVATE); break; default: - usageError("main.illegal_option_value", arg); + String text = getLocalizedMessage("main.illegal_option_value", arg); + throw new IllegalOptionValue(this::usage, text); } } - void setFilter(ToolOption opt, String arg) { + void setFilter(ToolOption opt, String arg) throws OptionException { jdtoolOpts.put(opt, getAccessValue(arg)); } - void setSimpleFilter(String arg) { + void setSimpleFilter(String arg) throws OptionException { handleSimpleOption(arg); } @@ -532,7 +547,7 @@ public enum ToolOption { fileManagerOpts.put(opt, arg); } - void handleSimpleOption(String arg) { + void handleSimpleOption(String arg) throws OptionException { populateSimpleAccessMap(getAccessValue(arg)); } @@ -541,7 +556,7 @@ public enum ToolOption { * -private, so on, in addition to the new ones such as * --show-types:public and so on. */ - private AccessKind getAccessValue(String arg) { + private AccessKind getAccessValue(String arg) throws OptionException { int colon = arg.indexOf(':'); String value = (colon > 0) ? arg.substring(colon + 1) @@ -556,8 +571,8 @@ public enum ToolOption { case "private": return AccessKind.PRIVATE; default: - usageError("main.illegal_option_value", value); - return null; + String text = getLocalizedMessage("main.illegal_option_value", value); + throw new IllegalOptionValue(this::usage, text); } } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties index c5edf9f16fe..89cfe162593 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties @@ -265,13 +265,13 @@ main.Loading_source_file=Loading source file {0}... main.Building_tree=Constructing Javadoc information... main.no_source_files_for_package=No source files for package {0} main.package_not_found=Package {0} not found -main.fatal.error=fatal error -main.fatal.exception=fatal exception +main.fatal.error=fatal error encountered: {0} main.out.of.memory=java.lang.OutOfMemoryError: Please increase memory.\n\ For example, on the JDK Classic or HotSpot VMs, add the option -J-Xmx\n\ such as -J-Xmx32m. main.done_in=[done in {0} ms] main.more_than_one_doclet_specified_0_and_1=More than one doclet specified ({0} and {1}). +main.doclet_could_not_get_location=Could not get location for {0} main.doclet_could_not_set_location=Could not set location for {0} main.doclet_no_classloader_found=Could not obtain classloader to load {0} main.could_not_instantiate_class=Could not instantiate class {0} @@ -286,7 +286,15 @@ main.illegal_option_value=Illegal option value: "{0}" main.release.bootclasspath.conflict=option {0} cannot be used together with -release main.unsupported.release.version=release version {0} not supported main.release.not.standard.file.manager=-release option specified, but the provided JavaFileManager is not a StandardJavaFileManager. +main.file.manager.list=FileManager error listing files: "{0}" +main.assertion.error=assertion failed: "{0}}" main.unknown.error=an unknown error has occurred +main.internal.error=an internal error has occurred +main.unexpected.exception=an unexpected exception was caught: {0} +doclet.internal.report.bug=\ +Please file a bug against the javadoc tool via the Java bug reporting page\n\ +(http://bugreport.java.com) after checking the Bug Database (http://bugs.java.com)\n\ +for duplicates. Include error messages and the following diagnostic in your report. Thank you. main.legacy_api=The old Doclet and Taglet APIs in the packages\n\ com.sun.javadoc, com.sun.tools.doclets and their implementations\n\ are planned to be removed in a future JDK release. These\n\ diff --git a/langtools/src/jdk.javadoc/share/classes/module-info.java b/langtools/src/jdk.javadoc/share/classes/module-info.java index 8d957e00c41..89c5d728fdd 100644 --- a/langtools/src/jdk.javadoc/share/classes/module-info.java +++ b/langtools/src/jdk.javadoc/share/classes/module-info.java @@ -41,6 +41,9 @@ module jdk.javadoc { exports jdk.javadoc.doclet.taglet; exports jdk.javadoc.doclets; + provides java.util.spi.ToolProvider + with jdk.javadoc.internal.tool.JavadocToolProvider; + provides javax.tools.DocumentationTool with jdk.javadoc.internal.api.JavadocTool; } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/Main.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/Main.java index 20f1ab3c1ae..9bcd3d37ab1 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/Main.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package com.sun.tools.javap; import java.io.PrintWriter; +import java.util.spi.ToolProvider; /** * Main entry point. @@ -58,4 +59,14 @@ public class Main { t.setLog(out); return t.run(args); } + + public static class JavapToolProvider implements ToolProvider { + public String name() { + return "javap"; + } + + public int run(PrintWriter out, PrintWriter err, String... args) { + return Main.run(args, out); + } + } } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Main.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Main.java index 3a024981393..fd05a76da1c 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Main.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Main.java @@ -89,8 +89,6 @@ import javax.lang.model.element.TypeElement; * - multi-version jar */ public class Main implements DiagnosticListener { - public static Main instance; - final PrintStream out; final PrintStream err; final List bootClassPath = new ArrayList<>(); @@ -414,13 +412,6 @@ public class Main implements DiagnosticListener { } } - /** - * Prints a usage message to the err stream. - */ - void usage() { - - } - /** * An enum denoting the mode in which the tool is running. * Different modes correspond to the different process* methods. @@ -504,7 +495,6 @@ public class Main implements DiagnosticListener { args.remove(); switch (a) { case "--class-path": - case "-cp": classPath.clear(); Arrays.stream(args.remove().split(File.pathSeparator)) .map(File::new) @@ -699,12 +689,7 @@ public class Main implements DiagnosticListener { * @return true on success, false otherwise */ public static boolean call(PrintStream out, PrintStream err, String... args) { - try { - instance = new Main(out, err); - return instance.run(args); - } finally { - instance = null; - } + return new Main(out, err).run(args); } /** diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/readme.md b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/readme.md index f51a1ea0c9b..5875e4efa9a 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/readme.md +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/readme.md @@ -39,7 +39,6 @@ JDeprScan Tool Command Reference **OPTIONS** - -cp PATH --class-path PATH Sets the classpath to PATH. @@ -103,7 +102,7 @@ For example, the `Thread.State` enum would be specified using the string java.lang.Thread$State -The `--class-path` and `-cp` options specify the classpath used for +The `--class-path` option specifies the classpath used for class searching. The classpath is used for classes named on the command line, as well as for dependencies of the classes in jar file or directory hierarchy to be scanned. diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/resources/jdeprscan.properties b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/resources/jdeprscan.properties index fd92fe813ee..71b85abfe5c 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/resources/jdeprscan.properties +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/resources/jdeprscan.properties @@ -2,7 +2,7 @@ main.usage=\ Usage: jdeprscan [options] '{dir|jar|class}' ...\n\ \n\ options:\n\ -\ -cp --class-path PATH\n\ +\ --class-path PATH\n\ \ --for-removal\n\ \ --full-version\n\ \ -h --help\n\ @@ -20,7 +20,7 @@ for nested classes, for example,\n\ \n\ \ java.lang.Thread$State\n\ \n\ -The --class-path (-cp) option provides a search path for resolution\n\ +The --class-path option provides a search path for resolution\n\ of dependent classes.\n\ \n\ The --for-removal option limits scanning or listing to APIs that are\n\ diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java index a72a5152d3c..9ad023c5df5 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java @@ -63,7 +63,7 @@ public class ClassFileReader implements Closeable { * Returns a ClassFileReader instance of a given path. */ public static ClassFileReader newInstance(Path path) throws IOException { - return newInstance(path, JarFile.baseVersion()); + return newInstance(path, null); } /** @@ -438,7 +438,10 @@ public class ClassFileReader implements Closeable { cf = reader.readClassFile(jf, nextEntry); return true; } catch (ClassFileError | IOException ex) { - skippedEntries.add(nextEntry.getName()); + skippedEntries.add(String.format("%s: %s (%s)", + ex.getMessage(), + nextEntry.getName(), + jf.getName())); } nextEntry = nextEntry(); } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java index 3bacd6fc034..9f7e0d232f7 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java @@ -483,6 +483,7 @@ class JdepsTask { } if (options.checkModuleDeps != null && !inputArgs.isEmpty()) { reportError("err.invalid.module.option", inputArgs, "--check"); + return EXIT_CMDERR; } boolean ok = run(); @@ -604,11 +605,12 @@ class JdepsTask { boolean ok = analyzer.run(options.compileTimeView, options.depth); // print skipped entries, if any - analyzer.archives() - .forEach(archive -> archive.reader() - .skippedEntries().stream() - .forEach(name -> warning("warn.skipped.entry", - name, archive.getPathName()))); + if (!options.nowarning) { + analyzer.archives() + .forEach(archive -> archive.reader() + .skippedEntries().stream() + .forEach(name -> warning("warn.skipped.entry", name))); + } if (options.findJDKInternals && !options.nowarning) { Map jdkInternals = new TreeMap<>(); @@ -676,17 +678,29 @@ class JdepsTask { } private boolean genModuleInfo(JdepsConfiguration config) throws IOException { + // check if any JAR file contains unnamed package + for (String arg : inputArgs) { + Optional classInUnnamedPackage = + ClassFileReader.newInstance(Paths.get(arg)) + .entries().stream() + .filter(n -> n.endsWith(".class")) + .filter(cn -> toPackageName(cn).isEmpty()) + .findFirst(); + + if (classInUnnamedPackage.isPresent()) { + if (classInUnnamedPackage.get().equals("module-info.class")) { + reportError("err.genmoduleinfo.not.jarfile", arg); + } else { + reportError("err.genmoduleinfo.unnamed.package", arg); + } + return false; + } + } + ModuleInfoBuilder builder = new ModuleInfoBuilder(config, inputArgs, options.genModuleInfo); boolean ok = builder.run(); - builder.modules().forEach(module -> { - if (module.packages().contains("")) { - reportError("ERROR: %s contains unnamed package. " + - "module-info.java not generated%n", module.getPathName()); - } - }); - if (!ok && !options.nowarning) { log.println("ERROR: missing dependencies"); builder.visitMissingDeps( @@ -703,6 +717,11 @@ class JdepsTask { return ok; } + private String toPackageName(String name) { + int i = name.lastIndexOf('/'); + return i > 0 ? name.replace('/', '.').substring(0, i) : ""; + } + /** * Returns a filter used during dependency analysis */ diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Main.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Main.java index a693062206a..aa8e116400c 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Main.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package com.sun.tools.jdeps; import java.io.*; +import java.util.spi.ToolProvider; /** * @@ -62,4 +63,14 @@ public class Main { t.setLog(out); return t.run(args); } + + public static class JDepsToolProvider implements ToolProvider { + public String name() { + return "jdeps"; + } + + public int run(PrintWriter out, PrintWriter err, String... args) { + return Main.run(args, out); + } + } } diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties index c2858c84120..7a26794260b 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties @@ -166,7 +166,8 @@ err.unknown.option=unknown option: {0} err.missing.arg=no value given for {0} err.invalid.arg.for.option=invalid argument for option: {0} err.option.after.class=option must be specified before classes: {0} -err.genmoduleinfo.not.jarfile={0} not valid for --generate-module-info option (must be non-modular JAR file) +err.genmoduleinfo.not.jarfile={0} is a modular JAR file that cannot be specified with the --generate-module-info option +err.genmoduleinfo.unnamed.package={0} contains an unnamed package that is not allowed in a module err.profiles.msg=No profile information err.exception.message={0} err.invalid.path=invalid path: {0} @@ -180,6 +181,7 @@ err.multirelease.option.notfound={0} is a multi-release jar file, but the --mult err.multirelease.version.associated=class {0} already associated with version {1}, trying to add version {2} err.multirelease.jar.malformed=malformed multi-release jar, {0}, bad entry: {1} warn.invalid.arg=Path does not exist: {0} +warn.skipped.entry={0} warn.split.package=package {0} defined in {1} {2} warn.replace.useJDKInternals=\ JDK internal APIs are unsupported and private to JDK implementation that are\n\ diff --git a/langtools/src/jdk.jdeps/share/classes/module-info.java b/langtools/src/jdk.jdeps/share/classes/module-info.java index 5bbdddedcfc..7c1240dd907 100644 --- a/langtools/src/jdk.jdeps/share/classes/module-info.java +++ b/langtools/src/jdk.jdeps/share/classes/module-info.java @@ -32,4 +32,10 @@ module jdk.jdeps { requires jdk.compiler; exports com.sun.tools.classfile to jdk.jlink; + + provides java.util.spi.ToolProvider + with com.sun.tools.javap.Main.JavapToolProvider; + + provides java.util.spi.ToolProvider + with com.sun.tools.jdeps.Main.JDepsToolProvider; } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java index c652b45b308..fc52ac0c9e1 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java @@ -166,6 +166,7 @@ class CompletenessAnalyzer { private static final int XTERM = 0b100000000; // Can terminate (last before EOF) private static final int XSTART = 0b1000000000; // Boundary, must be XTERM before private static final int XERRO = 0b10000000000; // Is an error + private static final int XBRACESNEEDED = 0b100000000000; // Expect {ANY} LBRACE /** * An extension of the compiler's TokenKind which adds our combined/processed @@ -190,7 +191,7 @@ class CompletenessAnalyzer { ERROR(TokenKind.ERROR, XERRO), // IDENTIFIER(TokenKind.IDENTIFIER, XEXPR1|XDECL1|XTERM), // UNDERSCORE(TokenKind.UNDERSCORE, XERRO), // _ - CLASS(TokenKind.CLASS, XEXPR|XDECL1), // class decl (MAPPED: DOTCLASS) + CLASS(TokenKind.CLASS, XEXPR|XDECL1|XBRACESNEEDED), // class decl (MAPPED: DOTCLASS) MONKEYS_AT(TokenKind.MONKEYS_AT, XEXPR|XDECL1), // @ IMPORT(TokenKind.IMPORT, XDECL1|XSTART), // import -- consider declaration SEMI(TokenKind.SEMI, XSTMT1|XTERM|XSTART), // ; @@ -202,10 +203,10 @@ class CompletenessAnalyzer { CUSTOM(TokenKind.CUSTOM, XERRO), // No uses // Declarations - ENUM(TokenKind.ENUM, XDECL1), // enum + ENUM(TokenKind.ENUM, XDECL1|XBRACESNEEDED), // enum IMPLEMENTS(TokenKind.IMPLEMENTS, XDECL), // implements - INTERFACE(TokenKind.INTERFACE, XDECL1), // interface - THROWS(TokenKind.THROWS, XDECL), // throws + INTERFACE(TokenKind.INTERFACE, XDECL1|XBRACESNEEDED), // interface + THROWS(TokenKind.THROWS, XDECL|XBRACESNEEDED), // throws // Primarive type names BOOLEAN(TokenKind.BOOLEAN, XEXPR1|XDECL1), // boolean @@ -381,6 +382,10 @@ class CompletenessAnalyzer { return (belongs & XSTART) != 0; } + boolean isBracesNeeded() { + return (belongs & XBRACESNEEDED) != 0; + } + /** * After construction, check that all compiler TokenKind values have * corresponding TK values. @@ -641,7 +646,9 @@ class CompletenessAnalyzer { public Completeness parseDeclaration() { boolean isImport = token.kind == IMPORT; + boolean isBracesNeeded = false; while (token.kind.isDeclaration()) { + isBracesNeeded |= token.kind.isBracesNeeded(); nextToken(); } switch (token.kind) { @@ -666,6 +673,9 @@ class CompletenessAnalyzer { case SEMI: return Completeness.COMPLETE; case IDENTIFIER: + return isBracesNeeded + ? Completeness.DEFINITELY_INCOMPLETE + : Completeness.COMPLETE_WITH_SEMI; case BRACKETS: return Completeness.COMPLETE_WITH_SEMI; case DOTSTAR: diff --git a/langtools/test/Makefile b/langtools/test/Makefile index d573f1fc402..f92e7611a97 100644 --- a/langtools/test/Makefile +++ b/langtools/test/Makefile @@ -157,6 +157,15 @@ ifdef TESTBOOTCLASSPATH -refvmoptions:-Xbootclasspath/p:$(TESTBOOTCLASSPATH) endif +ifeq ($(ARCH_DATA_MODEL),32) + # Set the GC options for test vms + JTREG_GC_OPTION = -vmoption:-XX:+UseSerialGC + JTREG_OPTIONS += $(JTREG_GC_OPTION) +endif +# Set the max memory for jtreg target test JVMs +JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx768m +JTREG_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION) + ifdef EXTRA_JTREG_OPTIONS JTREG_OPTIONS += $(EXTRA_JTREG_OPTIONS) endif @@ -304,8 +313,6 @@ jtreg-tests: check-jtreg FRC $(JTREG_OUTPUT_DIR)/diff.html $(JTREG_OUTPUT_DIR)/status.txt @mkdir -p $(JTREG_OUTPUT_DIR) JT_JAVA=$(JT_JAVA) $(JTREG) \ - -J-Xmx512m \ - -vmoption:-Xmx768m \ -a -ignore:quiet $(if $(JTREG_VERBOSE),-v:$(JTREG_VERBOSE)) \ -r:$(JTREG_OUTPUT_DIR)/JTreport \ -w:$(JTREG_OUTPUT_DIR)/JTwork \ diff --git a/langtools/test/jdk/javadoc/doclet/T6735320/T6735320.java b/langtools/test/jdk/javadoc/doclet/T6735320/T6735320.java index 23eba5fd30a..6f36bee159b 100644 --- a/langtools/test/jdk/javadoc/doclet/T6735320/T6735320.java +++ b/langtools/test/jdk/javadoc/doclet/T6735320/T6735320.java @@ -42,7 +42,7 @@ public class T6735320 extends JavadocTester { void test() { javadoc("-d", "out", testSrc("SerialFieldTest.java")); - checkExit(Exit.FAILED); + checkExit(Exit.ERROR); checkOutput(Output.STDERR, false, "OutOfBoundsException"); } diff --git a/langtools/test/jdk/javadoc/doclet/dupThrowsTags/TestDupThrowsTags.java b/langtools/test/jdk/javadoc/doclet/dupThrowsTags/TestDupThrowsTags.java index ecdb2952dc5..cf5261f8826 100644 --- a/langtools/test/jdk/javadoc/doclet/dupThrowsTags/TestDupThrowsTags.java +++ b/langtools/test/jdk/javadoc/doclet/dupThrowsTags/TestDupThrowsTags.java @@ -42,7 +42,7 @@ public class TestDupThrowsTags extends JavadocTester { void test() { javadoc("-d", "out", testSrc("TestDupThrowsTags.java")); - checkExit(Exit.FAILED); + checkExit(Exit.ERROR); checkOutput("TestDupThrowsTags.html", true, "Test 1 passes", diff --git a/langtools/test/jdk/javadoc/doclet/lib/JavadocTester.java b/langtools/test/jdk/javadoc/doclet/lib/JavadocTester.java index f047ad126e1..5e4caa79e89 100644 --- a/langtools/test/jdk/javadoc/doclet/lib/JavadocTester.java +++ b/langtools/test/jdk/javadoc/doclet/lib/JavadocTester.java @@ -327,15 +327,27 @@ public abstract class JavadocTester { outputDirectoryCheck = c; } + /** + * The exit codes returned by the javadoc tool. + * @see jdk.javadoc.internal.tool.Main.Result + */ public enum Exit { - OK(0), - FAILED(1); + OK(0), // Javadoc completed with no errors. + ERROR(1), // Completed but reported errors. + CMDERR(2), // Bad command-line arguments + SYSERR(3), // System error or resource exhaustion. + ABNORMAL(4); // Javadoc terminated abnormally Exit(int code) { this.code = code; } final int code; + + @Override + public String toString() { + return name() + '(' + code + ')'; + } } /** @@ -349,7 +361,7 @@ public abstract class JavadocTester { if (exitCode == expected.code) { passed("return code " + exitCode); } else { - failed("return code " + exitCode +"; expected " + expected.code + " (" + expected + ")"); + failed("return code " + exitCode +"; expected " + expected); } } diff --git a/langtools/test/jdk/javadoc/doclet/testBadSourceFile/TestBadSourceFile.java b/langtools/test/jdk/javadoc/doclet/testBadSourceFile/TestBadSourceFile.java index 15f5fc13bdf..69aa7ab5be1 100644 --- a/langtools/test/jdk/javadoc/doclet/testBadSourceFile/TestBadSourceFile.java +++ b/langtools/test/jdk/javadoc/doclet/testBadSourceFile/TestBadSourceFile.java @@ -50,6 +50,6 @@ public class TestBadSourceFile extends JavadocTester { javadoc("-Xdoclint:none", "-d", "out", testSrc("C2.java")); - checkExit(Exit.FAILED); + checkExit(Exit.ERROR); } } diff --git a/langtools/test/jdk/javadoc/doclet/testConstantValuesPage/TestConstantValuesPage.java b/langtools/test/jdk/javadoc/doclet/testConstantValuesPage/TestConstantValuesPage.java index 0d674d7f523..d1371f1c589 100644 --- a/langtools/test/jdk/javadoc/doclet/testConstantValuesPage/TestConstantValuesPage.java +++ b/langtools/test/jdk/javadoc/doclet/testConstantValuesPage/TestConstantValuesPage.java @@ -45,7 +45,7 @@ public class TestConstantValuesPage extends JavadocTester { javadoc("-d", "out", "-sourcepath", testSrc, "foo"); - checkExit(Exit.FAILED); + checkExit(Exit.CMDERR); checkOutput(Output.OUT, false, "constant-values.html..."); diff --git a/langtools/test/jdk/javadoc/doclet/testDocErrorReporter/TestDocErrorReporter.java b/langtools/test/jdk/javadoc/doclet/testDocErrorReporter/TestDocErrorReporter.java index 76a0d2afb0c..27fc752d27d 100644 --- a/langtools/test/jdk/javadoc/doclet/testDocErrorReporter/TestDocErrorReporter.java +++ b/langtools/test/jdk/javadoc/doclet/testDocErrorReporter/TestDocErrorReporter.java @@ -52,6 +52,8 @@ public class TestDocErrorReporter extends JavadocTester { "-encoding", "xyz", testSrc("TestDocErrorReporter.java")); - checkExit(Exit.FAILED); + checkExit(Exit.ERROR); + + checkOutput(Output.OUT, true, "error: unsupported encoding: xyz"); } } diff --git a/langtools/test/jdk/javadoc/doclet/testHelpOption/TestHelpOption.java b/langtools/test/jdk/javadoc/doclet/testHelpOption/TestHelpOption.java index 44a3736595d..77c9726b5a4 100644 --- a/langtools/test/jdk/javadoc/doclet/testHelpOption/TestHelpOption.java +++ b/langtools/test/jdk/javadoc/doclet/testHelpOption/TestHelpOption.java @@ -111,7 +111,7 @@ public class TestHelpOption extends JavadocTester { "-helpfile", testSrc("test-help.html"), "-helpfile", testSrc("test-help.html"), testSrc("Sample.java")); - checkExit(Exit.FAILED); + checkExit(Exit.ERROR); } @Test @@ -121,7 +121,7 @@ public class TestHelpOption extends JavadocTester { "-helpfile", testSrc("test-help.html"), "-nohelp", testSrc("Sample.java")); - checkExit(Exit.FAILED); + checkExit(Exit.ERROR); } private void checkOutput(boolean withOption) { diff --git a/langtools/test/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java b/langtools/test/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java index a11386a05f4..8053f897ffe 100644 --- a/langtools/test/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java +++ b/langtools/test/jdk/javadoc/doclet/testHtmlTag/TestHtmlTag.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6786682 + * @bug 6786682 4649116 * @summary This test verifies the use of lang attribute by . * @author Bhavesh Patel * @library ../lib @@ -106,7 +106,7 @@ public class TestHtmlTag extends JavadocTester { checkExit(Exit.OK); checkOutput("pkg3/package-summary.html", true, - "

    Package pkg3 Description

    \n" + "
    \n" + "

    This is the first line." + " Note the newlines before the <p> is relevant.

    "); diff --git a/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java b/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java index e9dc703cbb9..7a7a77252d4 100644 --- a/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java +++ b/langtools/test/jdk/javadoc/doclet/testHtmlVersion/TestHtmlVersion.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8072945 8081854 8141492 8148985 8150188 + * @bug 8072945 8081854 8141492 8148985 8150188 4649116 * @summary Test the version of HTML generated by the javadoc tool. * @author bpatel * @library ../lib @@ -162,10 +162,17 @@ public class TestHtmlVersion extends JavadocTester { "
    \n" + "
    ", "
    \n" - + "

    Package pkg Description

    \n", + + "
    Test package.
    ", "