OpenJDK / amber / amber
changeset 11705:b96ca2cb3623
Merge
author | duke |
---|---|
date | Wed, 05 Jul 2017 18:01:59 +0200 |
parents | 3ef37abc6e33 f38292636847 |
children | 44f8a3f9de82 |
files | jdk/test/tools/launcher/ChangeDataModel.sh jdk/test/tools/launcher/CreatePlatformFile.java jdk/test/tools/launcher/SomeException.java jdk/test/tools/launcher/UnicodeCleanup.java jdk/test/tools/launcher/UnicodeTest.sh jdk/test/tools/launcher/deleteI18n.sh jdk/test/tools/launcher/i18nTest.sh jdk/test/tools/launcher/unresolvedExceptions.sh |
diffstat | 193 files changed, 9374 insertions(+), 3391 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags-top-repo Thu Feb 02 09:39:33 2012 -0800 +++ b/.hgtags-top-repo Wed Jul 05 18:01:59 2017 +0200 @@ -145,3 +145,4 @@ cc771d92284f71765eca14d6d08703c4af254c04 jdk8-b21 7ad075c809952e355d25030605da6af30456ed74 jdk8-b22 60d6f64a86b1e511169d264727f6d51415978df0 jdk8-b23 +1a5f1d6b98d6827cdb529a4abe6e52a886d944f4 jdk8-b24
--- a/corba/.hgtags Thu Feb 02 09:39:33 2012 -0800 +++ b/corba/.hgtags Wed Jul 05 18:01:59 2017 +0200 @@ -145,3 +145,4 @@ f157fc2a71a38ce44007a6f18d5b011824dce705 jdk8-b21 a11d0062c445d5f36651c78650ab88aa594bcbff jdk8-b22 5218eb256658442b62b05295aafa5b5f35252972 jdk8-b23 +b98f0e6dddf987df565029a1f58417fc1844c3f3 jdk8-b24
--- a/hotspot/.hgtags Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/.hgtags Wed Jul 05 18:01:59 2017 +0200 @@ -215,3 +215,6 @@ dcc292399a39113957eebbd3e487b7e05e2c79fc hs23-b11 e850d8e7ea54b91c7aa656e297f0f9f38dd4c296 jdk8-b23 9e177d44b10fe92ecffa965fef9c5ac5433c1b46 hs23-b12 +a80fd4f45d7aaa154ed2f86a129f3c9c4035ec7a jdk8-b24 +b22de824749922986ce4d442bed029916b832807 hs23-b13 +64b46f975ab82948c1e021e17775ff4fab8bc40e hs23-b14
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/LoaderConstraintTable.java Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/LoaderConstraintTable.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -42,15 +42,6 @@ private static synchronized void initialize(TypeDataBase db) { Type type = db.lookupType("LoaderConstraintTable"); - nofBuckets = db.lookupIntConstant("LoaderConstraintTable::_nof_buckets").intValue(); - } - - // Fields - private static int nofBuckets; - - // Accessors - public static int getNumOfBuckets() { - return nofBuckets; } public LoaderConstraintTable(Address addr) {
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -36,7 +36,6 @@ private static AddressField placeholdersField; private static AddressField loaderConstraintTableField; private static sun.jvm.hotspot.types.OopField javaSystemLoaderField; - private static int nofBuckets; private static sun.jvm.hotspot.types.OopField objectKlassField; private static sun.jvm.hotspot.types.OopField classLoaderKlassField; @@ -62,7 +61,6 @@ placeholdersField = type.getAddressField("_placeholders"); loaderConstraintTableField = type.getAddressField("_loader_constraints"); javaSystemLoaderField = type.getOopField("_java_system_loader"); - nofBuckets = db.lookupIntConstant("SystemDictionary::_nof_buckets").intValue(); objectKlassField = type.getOopField(WK_KLASS("Object_klass")); classLoaderKlassField = type.getOopField(WK_KLASS("ClassLoader_klass")); @@ -142,10 +140,6 @@ return newOop(javaSystemLoaderField.getValue()); } - public static int getNumOfBuckets() { - return nofBuckets; - } - private static Oop newOop(OopHandle handle) { return VM.getVM().getObjectHeap().newOop(handle); }
--- a/hotspot/make/Makefile Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/make/Makefile Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -89,19 +89,31 @@ ZERO_VM_TARGETS=productzero fastdebugzero optimizedzero jvmgzero SHARK_VM_TARGETS=productshark fastdebugshark optimizedshark jvmgshark +COMMON_VM_PRODUCT_TARGETS=product product1 productkernel docs export_product +COMMON_VM_FASTDEBUG_TARGETS=fastdebug fastdebug1 fastdebugkernel docs export_fastdebug +COMMON_VM_DEBUG_TARGETS=jvmg jvmg1 jvmgkernel docs export_debug + # JDK directory list JDK_DIRS=bin include jre lib demo all: all_product all_fastdebug -ifndef BUILD_CLIENT_ONLY -all_product: product product1 productkernel docs export_product -all_fastdebug: fastdebug fastdebug1 fastdebugkernel docs export_fastdebug -all_debug: jvmg jvmg1 jvmgkernel docs export_debug -else + +ifdef BUILD_CLIENT_ONLY all_product: product1 docs export_product all_fastdebug: fastdebug1 docs export_fastdebug all_debug: jvmg1 docs export_debug +else +ifeq ($(MACOSX_UNIVERSAL),true) +all_product: universal_product +all_fastdebug: universal_fastdebug +all_debug: universal_debug +else +all_product: $(COMMON_VM_PRODUCT_TARGETS) +all_fastdebug: $(COMMON_VM_FASTDEBUG_TARGETS) +all_debug: $(COMMON_VM_DEBUG_TARGETS) endif +endif + all_optimized: optimized optimized1 optimizedkernel docs export_optimized allzero: all_productzero all_fastdebugzero @@ -232,20 +244,19 @@ $(MAKE) VM_SUBDIR=${VM_DEBUG} EXPORT_SUBDIR=/debug generic_export export_optimized: $(MAKE) VM_SUBDIR=optimized EXPORT_SUBDIR=/optimized generic_export -export_product_jdk: +export_product_jdk:: $(MAKE) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) \ VM_SUBDIR=product generic_export -export_optimized_jdk: +export_optimized_jdk:: $(MAKE) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR) \ VM_SUBDIR=optimized generic_export -export_fastdebug_jdk: +export_fastdebug_jdk:: $(MAKE) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/fastdebug \ VM_SUBDIR=fastdebug generic_export -export_debug_jdk: +export_debug_jdk:: $(MAKE) ALT_EXPORT_PATH=$(JDK_IMAGE_DIR)/debug \ VM_SUBDIR=${VM_DEBUG} generic_export - # Export file copy rules XUSAGE=$(HS_SRC_DIR)/share/vm/Xusage.txt DOCS_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_docs @@ -444,14 +455,14 @@ endif $(JDK_IMAGE_DIR)/bin/java -server -version -copy_product_jdk: +copy_product_jdk:: $(RM) -r $(JDK_IMAGE_DIR) $(MKDIR) -p $(JDK_IMAGE_DIR) ($(CD) $(JDK_IMPORT_PATH) && \ $(TAR) -cf - $(JDK_DIRS)) | \ ($(CD) $(JDK_IMAGE_DIR) && $(TAR) -xf -) -copy_fastdebug_jdk: +copy_fastdebug_jdk:: $(RM) -r $(JDK_IMAGE_DIR)/fastdebug $(MKDIR) -p $(JDK_IMAGE_DIR)/fastdebug if [ -d $(JDK_IMPORT_PATH)/fastdebug ] ; then \ @@ -464,7 +475,7 @@ ($(CD) $(JDK_IMAGE_DIR)/fastdebug && $(TAR) -xf -) ; \ fi -copy_debug_jdk: +copy_debug_jdk:: $(RM) -r $(JDK_IMAGE_DIR)/debug $(MKDIR) -p $(JDK_IMAGE_DIR)/debug if [ -d $(JDK_IMPORT_PATH)/debug ] ; then \ @@ -481,36 +492,6 @@ ($(CD) $(JDK_IMAGE_DIR)/debug && $(TAR) -xf -) ; \ fi -# macosx universal builds - -ifeq ($(MACOSX_UNIVERSAL), true) -$(UNIVERSAL_LIPO_LIST): - lipo -create -output $@ $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) - -$(UNIVERSAL_COPY_LIST): - $(CP) $(EXPORT_JRE_LIB_DIR)/i386/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) $@ - -universalize: $(UNIVERSAL_LIPO_LIST) $(UNIVERSAL_COPY_LIST) -endif - -universal_product: - $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 MACOSX_UNIVERSAL=true all_product - $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 MACOSX_UNIVERSAL=true all_product - $(MKDIR) -p $(EXPORT_JRE_LIB_DIR)/{client,server} - $(QUIETLY) $(MAKE) MACOSX_UNIVERSAL=true universalize - -universal_fastdebug: - $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 MACOSX_UNIVERSAL=true all_fastdebug - $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 MACOSX_UNIVERSAL=true all_fastdebug - $(MKDIR) -p $(EXPORT_JRE_LIB_DIR)/{client,server} - $(QUIETLY) $(MAKE) MACOSX_UNIVERSAL=true universalize - -universal_debug: - $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 MACOSX_UNIVERSAL=true all_debug - $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 MACOSX_UNIVERSAL=true all_debug - $(MKDIR) -p $(EXPORT_JRE_LIB_DIR)/{client,server} - $(QUIETLY) $(MAKE) MACOSX_UNIVERSAL=true universalize - # # Check target # @@ -630,6 +611,13 @@ @$(ECHO) \ " $(MAKE) ALT_JDK_IMPORT_PATH=/opt/java/jdk$(JDK_VERSION)" +# Universal build support +ifeq ($(OS_VENDOR), Darwin) +ifeq ($(MACOSX_UNIVERSAL),true) +include $(GAMMADIR)/make/$(OSNAME)/makefiles/universal.gmk +endif +endif + # JPRT rule to build this workspace include $(GAMMADIR)/make/jprt.gmk @@ -639,6 +627,4 @@ export_product export_fastdebug export_debug export_optimized \ export_jdk_product export_jdk_fastdebug export_jdk_debug \ create_jdk copy_jdk update_jdk test_jdk \ - copy_product_jdk copy_fastdebug_jdk copy_debug_jdk universalize \ - universal_product - + copy_product_jdk copy_fastdebug_jdk copy_debug_jdk
--- a/hotspot/make/bsd/makefiles/defs.make Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/make/bsd/makefiles/defs.make Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -171,10 +171,36 @@ EXPORT_LIST += $(ADD_SA_BINARIES/$(HS_ARCH)) -UNIVERSAL_LIPO_LIST += $(EXPORT_JRE_LIB_DIR)/libjsig.$(LIBRARY_SUFFIX) -UNIVERSAL_LIPO_LIST += $(EXPORT_JRE_LIB_DIR)/libsaproc.$(LIBRARY_SUFFIX) -UNIVERSAL_LIPO_LIST += $(EXPORT_JRE_LIB_DIR)/server/libjvm.$(LIBRARY_SUFFIX) +# Universal build settings +ifeq ($(OS_VENDOR), Darwin) + # Build universal binaries by default on Mac OS X + MACOSX_UNIVERSAL = true + ifneq ($(ALT_MACOSX_UNIVERSAL),) + MACOSX_UNIVERSAL = $(ALT_MACOSX_UNIVERSAL) + endif + MAKE_ARGS += MACOSX_UNIVERSAL=$(MACOSX_UNIVERSAL) -UNIVERSAL_COPY_LIST += $(EXPORT_JRE_LIB_DIR)/server/Xusage.txt -UNIVERSAL_COPY_LIST += $(EXPORT_JRE_LIB_DIR)/client/Xusage.txt -UNIVERSAL_COPY_LIST += $(EXPORT_JRE_LIB_DIR)/client/libjvm.$(LIBRARY_SUFFIX) + # Universal settings + ifeq ($(MACOSX_UNIVERSAL), true) + + # Set universal export path but avoid using ARCH or PLATFORM subdirs + EXPORT_PATH=$(OUTPUTDIR)/export-universal$(EXPORT_SUBDIR) + ifneq ($(ALT_EXPORT_PATH),) + EXPORT_PATH=$(ALT_EXPORT_PATH) + endif + + # Set universal image dir + JDK_IMAGE_DIR=$(OUTPUTDIR)/jdk-universal$(EXPORT_SUBDIR) + + # Binaries to 'universalize' if built + UNIVERSAL_LIPO_LIST += $(EXPORT_JRE_LIB_DIR)/libjsig.$(LIBRARY_SUFFIX) + UNIVERSAL_LIPO_LIST += $(EXPORT_JRE_LIB_DIR)/libsaproc.$(LIBRARY_SUFFIX) + UNIVERSAL_LIPO_LIST += $(EXPORT_JRE_LIB_DIR)/server/libjvm.$(LIBRARY_SUFFIX) + UNIVERSAL_LIPO_LIST += $(EXPORT_JRE_LIB_DIR)/client/libjvm.$(LIBRARY_SUFFIX) + + # Files to simply copy in place + UNIVERSAL_COPY_LIST += $(EXPORT_JRE_LIB_DIR)/server/Xusage.txt + UNIVERSAL_COPY_LIST += $(EXPORT_JRE_LIB_DIR)/client/Xusage.txt + + endif +endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/make/bsd/makefiles/universal.gmk Wed Jul 05 18:01:59 2017 +0200 @@ -0,0 +1,113 @@ +# +# Copyright (c) 2006, 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. +# +# + +# macosx universal builds +universal_product: + $(MAKE) MACOSX_UNIVERSAL=true all_product_universal +universal_fastdebug: + $(MAKE) MACOSX_UNIVERSAL=true all_fastdebug_universal +universal_debug: + $(MAKE) MACOSX_UNIVERSAL=true all_debug_universal + + +# Universal builds include 1 or more architectures in a single binary +all_product_universal: +# $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_PRODUCT_TARGETS) + $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_PRODUCT_TARGETS) + $(QUIETLY) $(MAKE) EXPORT_SUBDIR= universalize +all_fastdebug_universal: +# $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_FASTDEBUG_TARGETS) + $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_FASTDEBUG_TARGETS) + $(QUIETLY) $(MAKE) EXPORT_SUBDIR=/fastdebug universalize +all_debug_universal: +# $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_DEBUG_TARGETS) + $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_DEBUG_TARGETS) + $(QUIETLY) $(MAKE) EXPORT_SUBDIR=/debug universalize + + +# Consolidate architecture builds into a single Universal binary +universalize: $(UNIVERSAL_LIPO_LIST) $(UNIVERSAL_COPY_LIST) + $(RM) -r $(EXPORT_PATH)/jre/lib/{i386,amd64} + + +# Package built libraries in a universal binary +$(UNIVERSAL_LIPO_LIST): + BUILT_LIPO_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) 2>/dev/null`"; \ + if [ -n "$${BUILT_LIPO_FILES}" ]; then \ + $(MKDIR) -p $(shell dirname $@); \ + lipo -create -output $@ $${BUILT_LIPO_FILES}; \ + fi + + +# Copy built non-universal binaries in place +$(UNIVERSAL_COPY_LIST): + BUILT_COPY_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) 2>/dev/null`"; \ + if [ -n "$${BUILT_COPY_FILES}" ]; then \ + for i in $${BUILT_COPY_FILES}; do \ + if [ -f $${i} ]; then \ + $(MKDIR) -p $(shell dirname $@); \ + $(CP) $${i} $@; \ + fi; \ + done; \ + fi + + +# Replace arch specific binaries with universal binaries +export_universal: + $(RM) -r $(EXPORT_PATH)/jre/lib/{i386,amd64} + $(RM) -r $(JDK_IMAGE_DIR)/jre/lib/{i386,amd64} + $(RM) $(JDK_IMAGE_DIR)/jre/lib/{client,server}/libjsig.$(LIBRARY_SUFFIX) + ($(CD) $(EXPORT_PATH) && \ + $(TAR) -cf - *) | \ + ($(CD) $(JDK_IMAGE_DIR) && $(TAR) -xpf -) + + +# Overlay universal binaries +copy_universal: + $(RM) -r $(JDK_IMAGE_DIR)$(COPY_SUBDIR)/jre/lib/{i386,amd64} + $(RM) $(JDK_IMAGE_DIR)$(COPY_SUBDIR)/jre/lib/{client,server}/libjsig.$(LIBRARY_SUFFIX) + ($(CD) $(EXPORT_PATH)$(COPY_SUBDIR) && \ + $(TAR) -cf - *) | \ + ($(CD) $(JDK_IMAGE_DIR)$(COPY_SUBDIR) && $(TAR) -xpf -) + + +# Additional processing for universal builds +export_product_jdk:: + $(MAKE) EXPORT_SUBDIR= export_universal +export_optimized_jdk:: + $(MAKE) EXPORT_SUBDIR= export_universal +export_fastdebug_jdk:: + $(MAKE) EXPORT_SUBDIR=/fastdebug export_universal +export_debug_jdk:: + $(MAKE) EXPORT_SUBDIR=/debug export_universal +copy_product_jdk:: + $(MAKE) COPY_SUBDIR= copy_universal +copy_fastdebug_jdk:: + $(MAKE) COPY_SUBDIR=/fastdebug copy_universal +copy_debug_jdk:: + $(MAKE) COPY_SUBDIR=/debug copy_universal + +.PHONY: universal_product universal_fastdebug universal_debug \ + all_product_universal all_fastdebug_universal all_debug_universal \ + universalize export_universal copy_universal
--- a/hotspot/make/defs.make Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/make/defs.make Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 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 @@ -185,6 +185,15 @@ BOOTDIR=$(ALT_BOOTDIR) endif +# Select name of the export directory and honor ALT overrides +EXPORT_PATH=$(OUTPUTDIR)/export-$(PLATFORM)$(EXPORT_SUBDIR) +ifneq ($(ALT_EXPORT_PATH),) + EXPORT_PATH=$(ALT_EXPORT_PATH) +endif + +# Default jdk image if one is created for you with create_jdk +JDK_IMAGE_DIR=$(OUTPUTDIR)/jdk-$(PLATFORM) + # The platform dependent defs.make defines platform specific variable such # as ARCH, EXPORT_LIST etc. We must place the include here after BOOTDIR is defined. include $(GAMMADIR)/make/$(OSNAME)/makefiles/defs.make @@ -263,15 +272,6 @@ # includes this make/defs.make file. MAKE_ARGS += HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) -# Select name of export directory -EXPORT_PATH=$(OUTPUTDIR)/export-$(PLATFORM)$(EXPORT_SUBDIR) -ifneq ($(ALT_EXPORT_PATH),) - EXPORT_PATH=$(ALT_EXPORT_PATH) -endif - -# Default jdk image if one is created for you with create_jdk -JDK_IMAGE_DIR=$(OUTPUTDIR)/jdk-$(PLATFORM) - # Various export sub directories EXPORT_INCLUDE_DIR = $(EXPORT_PATH)/include EXPORT_DOCS_DIR = $(EXPORT_PATH)/docs
--- a/hotspot/make/hotspot_version Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/make/hotspot_version Wed Jul 05 18:01:59 2017 +0200 @@ -35,7 +35,7 @@ HS_MAJOR_VER=23 HS_MINOR_VER=0 -HS_BUILD_NUMBER=12 +HS_BUILD_NUMBER=14 JDK_MAJOR_VER=1 JDK_MINOR_VER=8
--- a/hotspot/make/jprt.properties Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/make/jprt.properties Wed Jul 05 18:01:59 2017 +0200 @@ -438,12 +438,12 @@ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_ParNewGC, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_CMS, \ ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_G1, \ - ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_ParOldGC \ - ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_default, \ - ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_default_tiered, \ - ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ - ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_G1, \ - ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_ParOldGC + ${jprt.my.macosx.x64}-{product|fastdebug}-c2-GCOld_ParOldGC +# ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_default, \ +# ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_default_tiered, \ +# ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_ParallelGC, \ +# ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_G1, \ +# ${jprt.my.macosx.x64}-{product|fastdebug}-c2-jbb_ParOldGC jprt.my.windows.i586.test.targets = \ ${jprt.my.windows.i586}-{product|fastdebug}-{c1|c2}-jvm98, \
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -2134,6 +2134,7 @@ // address pseudos: make these names unlike instruction names to avoid confusion inline intptr_t load_pc_address( Register reg, int bytes_to_skip ); inline void load_contents(const AddressLiteral& addrlit, Register d, int offset = 0); + inline void load_bool_contents(const AddressLiteral& addrlit, Register d, int offset = 0); inline void load_ptr_contents(const AddressLiteral& addrlit, Register d, int offset = 0); inline void store_contents(Register s, const AddressLiteral& addrlit, Register temp, int offset = 0); inline void store_ptr_contents(Register s, const AddressLiteral& addrlit, Register temp, int offset = 0); @@ -2249,7 +2250,7 @@ // this platform we assume byte size inline void stbool(Register d, const Address& a) { stb(d, a); } - inline void ldbool(const Address& a, Register d) { ldsb(a, d); } + inline void ldbool(const Address& a, Register d) { ldub(a, d); } inline void movbool( bool boolconst, Register d) { mov( (int) boolconst, d); } // klass oop manipulations if compressed
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -692,6 +692,17 @@ } +inline void MacroAssembler::load_bool_contents(const AddressLiteral& addrlit, Register d, int offset) { + assert_not_delayed(); + if (ForceUnreachable) { + patchable_sethi(addrlit, d); + } else { + sethi(addrlit, d); + } + ldub(d, addrlit.low10() + offset, d); +} + + inline void MacroAssembler::load_ptr_contents(const AddressLiteral& addrlit, Register d, int offset) { assert_not_delayed(); if (ForceUnreachable) {
--- a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -42,7 +42,7 @@ #else define_pd_global(bool, ProfileInterpreter, true); #endif // CC_INTERP -define_pd_global(bool, TieredCompilation, true); +define_pd_global(bool, TieredCompilation, trueInTiered); define_pd_global(intx, CompileThreshold, 10000); define_pd_global(intx, BackEdgeThreshold, 140000);
--- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -28,6 +28,7 @@ #include "oops/markOop.hpp" #include "oops/methodOop.hpp" #include "oops/oop.inline.hpp" +#include "prims/methodHandles.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp"
--- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -321,6 +321,16 @@ return (r->reg2stack() + SharedRuntime::out_preserve_stack_slots()) * VMRegImpl::stack_slot_size; } +static VMRegPair reg64_to_VMRegPair(Register r) { + VMRegPair ret; + if (wordSize == 8) { + ret.set2(r->as_VMReg()); + } else { + ret.set_pair(r->successor()->as_VMReg(), r->as_VMReg()); + } + return ret; +} + // --------------------------------------------------------------------------- // Read the array of BasicTypes from a signature, and compute where the // arguments should go. Values in the VMRegPair regs array refer to 4-byte (VMRegImpl::stack_slot_size) @@ -1444,6 +1454,25 @@ } +static void move_ptr(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + // stack to stack + __ ld_ptr(FP, reg2offset(src.first()) + STACK_BIAS, L5); + __ st_ptr(L5, SP, reg2offset(dst.first()) + STACK_BIAS); + } else { + // stack to reg + __ ld_ptr(FP, reg2offset(src.first()) + STACK_BIAS, dst.first()->as_Register()); + } + } else if (dst.first()->is_stack()) { + // reg to stack + __ st_ptr(src.first()->as_Register(), SP, reg2offset(dst.first()) + STACK_BIAS); + } else { + __ mov(src.first()->as_Register(), dst.first()->as_Register()); + } +} + + // An oop arg. Must pass a handle not the oop itself static void object_move(MacroAssembler* masm, OopMap* map, @@ -1748,6 +1777,166 @@ } } + +static void save_or_restore_arguments(MacroAssembler* masm, + const int stack_slots, + const int total_in_args, + const int arg_save_area, + OopMap* map, + VMRegPair* in_regs, + BasicType* in_sig_bt) { + // if map is non-NULL then the code should store the values, + // otherwise it should load them. + if (map != NULL) { + // Fill in the map + for (int i = 0; i < total_in_args; i++) { + if (in_sig_bt[i] == T_ARRAY) { + if (in_regs[i].first()->is_stack()) { + int offset_in_older_frame = in_regs[i].first()->reg2stack() + SharedRuntime::out_preserve_stack_slots(); + map->set_oop(VMRegImpl::stack2reg(offset_in_older_frame + stack_slots)); + } else if (in_regs[i].first()->is_Register()) { + map->set_oop(in_regs[i].first()); + } else { + ShouldNotReachHere(); + } + } + } + } + + // Save or restore double word values + int handle_index = 0; + for (int i = 0; i < total_in_args; i++) { + int slot = handle_index + arg_save_area; + int offset = slot * VMRegImpl::stack_slot_size; + if (in_sig_bt[i] == T_LONG && in_regs[i].first()->is_Register()) { + const Register reg = in_regs[i].first()->as_Register(); + if (reg->is_global()) { + handle_index += 2; + assert(handle_index <= stack_slots, "overflow"); + if (map != NULL) { + __ stx(reg, SP, offset + STACK_BIAS); + } else { + __ ldx(SP, offset + STACK_BIAS, reg); + } + } + } else if (in_sig_bt[i] == T_DOUBLE && in_regs[i].first()->is_FloatRegister()) { + handle_index += 2; + assert(handle_index <= stack_slots, "overflow"); + if (map != NULL) { + __ stf(FloatRegisterImpl::D, in_regs[i].first()->as_FloatRegister(), SP, offset + STACK_BIAS); + } else { + __ ldf(FloatRegisterImpl::D, SP, offset + STACK_BIAS, in_regs[i].first()->as_FloatRegister()); + } + } + } + // Save floats + for (int i = 0; i < total_in_args; i++) { + int slot = handle_index + arg_save_area; + int offset = slot * VMRegImpl::stack_slot_size; + if (in_sig_bt[i] == T_FLOAT && in_regs[i].first()->is_FloatRegister()) { + handle_index++; + assert(handle_index <= stack_slots, "overflow"); + if (map != NULL) { + __ stf(FloatRegisterImpl::S, in_regs[i].first()->as_FloatRegister(), SP, offset + STACK_BIAS); + } else { + __ ldf(FloatRegisterImpl::S, SP, offset + STACK_BIAS, in_regs[i].first()->as_FloatRegister()); + } + } + } + +} + + +// Check GC_locker::needs_gc and enter the runtime if it's true. This +// keeps a new JNI critical region from starting until a GC has been +// forced. Save down any oops in registers and describe them in an +// OopMap. +static void check_needs_gc_for_critical_native(MacroAssembler* masm, + const int stack_slots, + const int total_in_args, + const int arg_save_area, + OopMapSet* oop_maps, + VMRegPair* in_regs, + BasicType* in_sig_bt) { + __ block_comment("check GC_locker::needs_gc"); + Label cont; + AddressLiteral sync_state(GC_locker::needs_gc_address()); + __ load_bool_contents(sync_state, G3_scratch); + __ cmp_zero_and_br(Assembler::equal, G3_scratch, cont); + __ delayed()->nop(); + + // Save down any values that are live in registers and call into the + // runtime to halt for a GC + OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, map, in_regs, in_sig_bt); + + __ mov(G2_thread, L7_thread_cache); + + __ set_last_Java_frame(SP, noreg); + + __ block_comment("block_for_jni_critical"); + __ call(CAST_FROM_FN_PTR(address, SharedRuntime::block_for_jni_critical), relocInfo::runtime_call_type); + __ delayed()->mov(L7_thread_cache, O0); + oop_maps->add_gc_map( __ offset(), map); + + __ restore_thread(L7_thread_cache); // restore G2_thread + __ reset_last_Java_frame(); + + // Reload all the register arguments + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, NULL, in_regs, in_sig_bt); + + __ bind(cont); +#ifdef ASSERT + if (StressCriticalJNINatives) { + // Stress register saving + OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, map, in_regs, in_sig_bt); + // Destroy argument registers + for (int i = 0; i < total_in_args; i++) { + if (in_regs[i].first()->is_Register()) { + const Register reg = in_regs[i].first()->as_Register(); + if (reg->is_global()) { + __ mov(G0, reg); + } + } else if (in_regs[i].first()->is_FloatRegister()) { + __ fneg(FloatRegisterImpl::D, in_regs[i].first()->as_FloatRegister(), in_regs[i].first()->as_FloatRegister()); + } + } + + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, NULL, in_regs, in_sig_bt); + } +#endif +} + +// Unpack an array argument into a pointer to the body and the length +// if the array is non-null, otherwise pass 0 for both. +static void unpack_array_argument(MacroAssembler* masm, VMRegPair reg, BasicType in_elem_type, VMRegPair body_arg, VMRegPair length_arg) { + // Pass the length, ptr pair + Label is_null, done; + if (reg.first()->is_stack()) { + VMRegPair tmp = reg64_to_VMRegPair(L2); + // Load the arg up from the stack + move_ptr(masm, reg, tmp); + reg = tmp; + } + __ cmp(reg.first()->as_Register(), G0); + __ brx(Assembler::equal, false, Assembler::pt, is_null); + __ delayed()->add(reg.first()->as_Register(), arrayOopDesc::base_offset_in_bytes(in_elem_type), L4); + move_ptr(masm, reg64_to_VMRegPair(L4), body_arg); + __ ld(reg.first()->as_Register(), arrayOopDesc::length_offset_in_bytes(), L4); + move32_64(masm, reg64_to_VMRegPair(L4), length_arg); + __ ba_short(done); + __ bind(is_null); + // Pass zeros + move_ptr(masm, reg64_to_VMRegPair(G0), body_arg); + move32_64(masm, reg64_to_VMRegPair(G0), length_arg); + __ bind(done); +} + // --------------------------------------------------------------------------- // Generate a native wrapper for a given method. The method takes arguments // in the Java compiled code convention, marshals them to the native @@ -1762,6 +1951,13 @@ BasicType *in_sig_bt, VMRegPair *in_regs, BasicType ret_type) { + bool is_critical_native = true; + address native_func = method->critical_native_function(); + if (native_func == NULL) { + native_func = method->native_function(); + is_critical_native = false; + } + assert(native_func != NULL, "must have function"); // Native nmethod wrappers never take possesion of the oop arguments. // So the caller will gc the arguments. The only thing we need an @@ -1841,22 +2037,70 @@ // we convert the java signature to a C signature by inserting // the hidden arguments as arg[0] and possibly arg[1] (static method) - int total_c_args = total_in_args + 1; - if (method->is_static()) { - total_c_args++; + int total_c_args = total_in_args; + int total_save_slots = 6 * VMRegImpl::slots_per_word; + if (!is_critical_native) { + total_c_args += 1; + if (method->is_static()) { + total_c_args++; + } + } else { + for (int i = 0; i < total_in_args; i++) { + if (in_sig_bt[i] == T_ARRAY) { + // These have to be saved and restored across the safepoint + total_c_args++; + } + } } BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_c_args); - VMRegPair * out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args); + VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args); + BasicType* in_elem_bt = NULL; int argc = 0; - out_sig_bt[argc++] = T_ADDRESS; - if (method->is_static()) { - out_sig_bt[argc++] = T_OBJECT; - } - - for (int i = 0; i < total_in_args ; i++ ) { - out_sig_bt[argc++] = in_sig_bt[i]; + if (!is_critical_native) { + out_sig_bt[argc++] = T_ADDRESS; + if (method->is_static()) { + out_sig_bt[argc++] = T_OBJECT; + } + + for (int i = 0; i < total_in_args ; i++ ) { + out_sig_bt[argc++] = in_sig_bt[i]; + } + } else { + Thread* THREAD = Thread::current(); + in_elem_bt = NEW_RESOURCE_ARRAY(BasicType, total_in_args); + SignatureStream ss(method->signature()); + for (int i = 0; i < total_in_args ; i++ ) { + if (in_sig_bt[i] == T_ARRAY) { + // Arrays are passed as int, elem* pair + out_sig_bt[argc++] = T_INT; + out_sig_bt[argc++] = T_ADDRESS; + Symbol* atype = ss.as_symbol(CHECK_NULL); + const char* at = atype->as_C_string(); + if (strlen(at) == 2) { + assert(at[0] == '[', "must be"); + switch (at[1]) { + case 'B': in_elem_bt[i] = T_BYTE; break; + case 'C': in_elem_bt[i] = T_CHAR; break; + case 'D': in_elem_bt[i] = T_DOUBLE; break; + case 'F': in_elem_bt[i] = T_FLOAT; break; + case 'I': in_elem_bt[i] = T_INT; break; + case 'J': in_elem_bt[i] = T_LONG; break; + case 'S': in_elem_bt[i] = T_SHORT; break; + case 'Z': in_elem_bt[i] = T_BOOLEAN; break; + default: ShouldNotReachHere(); + } + } + } else { + out_sig_bt[argc++] = in_sig_bt[i]; + in_elem_bt[i] = T_VOID; + } + if (in_sig_bt[i] != T_VOID) { + assert(in_sig_bt[i] == ss.type(), "must match"); + ss.next(); + } + } } // Now figure out where the args must be stored and how much stack space @@ -1866,6 +2110,35 @@ int out_arg_slots; out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); + if (is_critical_native) { + // Critical natives may have to call out so they need a save area + // for register arguments. + int double_slots = 0; + int single_slots = 0; + for ( int i = 0; i < total_in_args; i++) { + if (in_regs[i].first()->is_Register()) { + const Register reg = in_regs[i].first()->as_Register(); + switch (in_sig_bt[i]) { + case T_ARRAY: + case T_BOOLEAN: + case T_BYTE: + case T_SHORT: + case T_CHAR: + case T_INT: assert(reg->is_in(), "don't need to save these"); break; + case T_LONG: if (reg->is_global()) double_slots++; break; + default: ShouldNotReachHere(); + } + } else if (in_regs[i].first()->is_FloatRegister()) { + switch (in_sig_bt[i]) { + case T_FLOAT: single_slots++; break; + case T_DOUBLE: double_slots++; break; + default: ShouldNotReachHere(); + } + } + } + total_save_slots = double_slots * 2 + single_slots; + } + // Compute framesize for the wrapper. We need to handlize all oops in // registers. We must create space for them here that is disjoint from // the windowed save area because we have no control over when we might @@ -1885,12 +2158,11 @@ // Now the space for the inbound oop handle area - int oop_handle_offset = stack_slots; - stack_slots += 6*VMRegImpl::slots_per_word; + int oop_handle_offset = round_to(stack_slots, 2); + stack_slots += total_save_slots; // Now any space we need for handlizing a klass if static method - int oop_temp_slot_offset = 0; int klass_slot_offset = 0; int klass_offset = -1; int lock_slot_offset = 0; @@ -1954,6 +2226,10 @@ __ verify_thread(); + if (is_critical_native) { + check_needs_gc_for_critical_native(masm, stack_slots, total_in_args, + oop_handle_offset, oop_maps, in_regs, in_sig_bt); + } // // We immediately shuffle the arguments so that any vm call we have to @@ -1982,7 +2258,6 @@ // caller. // OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); - int c_arg = total_c_args - 1; // Record sp-based slot for receiver on stack for non-static methods int receiver_offset = -1; @@ -2002,7 +2277,7 @@ #endif /* ASSERT */ - for ( int i = total_in_args - 1; i >= 0 ; i--, c_arg-- ) { + for ( int i = total_in_args - 1, c_arg = total_c_args - 1; i >= 0 ; i--, c_arg-- ) { #ifdef ASSERT if (in_regs[i].first()->is_Register()) { @@ -2019,7 +2294,13 @@ switch (in_sig_bt[i]) { case T_ARRAY: + if (is_critical_native) { + unpack_array_argument(masm, in_regs[i], in_elem_bt[i], out_regs[c_arg], out_regs[c_arg - 1]); + c_arg--; + break; + } case T_OBJECT: + assert(!is_critical_native, "no oop arguments"); object_move(masm, map, oop_handle_offset, stack_slots, in_regs[i], out_regs[c_arg], ((i == 0) && (!is_static)), &receiver_offset); @@ -2029,7 +2310,7 @@ case T_FLOAT: float_move(masm, in_regs[i], out_regs[c_arg]); - break; + break; case T_DOUBLE: assert( i + 1 < total_in_args && @@ -2051,7 +2332,7 @@ // Pre-load a static method's oop into O1. Used both by locking code and // the normal JNI call code. - if (method->is_static()) { + if (method->is_static() && !is_critical_native) { __ set_oop_constant(JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror()), O1); // Now handlize the static class mirror in O1. It's known not-null. @@ -2064,13 +2345,13 @@ const Register L6_handle = L6; if (method->is_synchronized()) { + assert(!is_critical_native, "unhandled"); __ mov(O1, L6_handle); } // We have all of the arguments setup at this point. We MUST NOT touch any Oregs // except O6/O7. So if we must call out we must push a new frame. We immediately // push a new frame and flush the windows. - #ifdef _LP64 intptr_t thepc = (intptr_t) __ pc(); { @@ -2202,32 +2483,28 @@ } // get JNIEnv* which is first argument to native - - __ add(G2_thread, in_bytes(JavaThread::jni_environment_offset()), O0); + if (!is_critical_native) { + __ add(G2_thread, in_bytes(JavaThread::jni_environment_offset()), O0); + } // Use that pc we placed in O7 a while back as the current frame anchor - __ set_last_Java_frame(SP, O7); + // We flushed the windows ages ago now mark them as flushed before transitioning. + __ set(JavaFrameAnchor::flushed, G3_scratch); + __ st(G3_scratch, G2_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::flags_offset()); + // Transition from _thread_in_Java to _thread_in_native. __ set(_thread_in_native, G3_scratch); - __ st(G3_scratch, G2_thread, JavaThread::thread_state_offset()); - - // We flushed the windows ages ago now mark them as flushed - - // mark windows as flushed - __ set(JavaFrameAnchor::flushed, G3_scratch); - - Address flags(G2_thread, JavaThread::frame_anchor_offset() + JavaFrameAnchor::flags_offset()); #ifdef _LP64 - AddressLiteral dest(method->native_function()); + AddressLiteral dest(native_func); __ relocate(relocInfo::runtime_call_type); __ jumpl_to(dest, O7, O7); #else - __ call(method->native_function(), relocInfo::runtime_call_type); + __ call(native_func, relocInfo::runtime_call_type); #endif - __ delayed()->st(G3_scratch, flags); + __ delayed()->st(G3_scratch, G2_thread, JavaThread::thread_state_offset()); __ restore_thread(L7_thread_cache); // restore G2_thread @@ -2259,6 +2536,7 @@ ShouldNotReachHere(); } + Label after_transition; // must we block? // Block, if necessary, before resuming in _thread_in_Java state. @@ -2303,22 +2581,34 @@ // a distinct one for this pc // save_native_result(masm, ret_type, stack_slots); - __ call_VM_leaf(L7_thread_cache, - CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans), - G2_thread); + if (!is_critical_native) { + __ call_VM_leaf(L7_thread_cache, + CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans), + G2_thread); + } else { + __ call_VM_leaf(L7_thread_cache, + CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans_and_transition), + G2_thread); + } // Restore any method result value restore_native_result(masm, ret_type, stack_slots); + + if (is_critical_native) { + // The call above performed the transition to thread_in_Java so + // skip the transition logic below. + __ ba(after_transition); + __ delayed()->nop(); + } + __ bind(no_block); } // thread state is thread_in_native_trans. Any safepoint blocking has already // happened so we can now change state to _thread_in_Java. - - __ set(_thread_in_Java, G3_scratch); __ st(G3_scratch, G2_thread, JavaThread::thread_state_offset()); - + __ bind(after_transition); Label no_reguard; __ ld(G2_thread, JavaThread::stack_guard_state_offset(), G3_scratch); @@ -2416,12 +2706,14 @@ __ verify_oop(I0); } - // reset handle block - __ ld_ptr(G2_thread, in_bytes(JavaThread::active_handles_offset()), L5); - __ st_ptr(G0, L5, JNIHandleBlock::top_offset_in_bytes()); - - __ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), G3_scratch); - check_forward_pending_exception(masm, G3_scratch); + if (!is_critical_native) { + // reset handle block + __ ld_ptr(G2_thread, in_bytes(JavaThread::active_handles_offset()), L5); + __ st_ptr(G0, L5, JNIHandleBlock::top_offset_in_bytes()); + + __ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), G3_scratch); + check_forward_pending_exception(masm, G3_scratch); + } // Return @@ -2450,6 +2742,10 @@ (is_static ? in_ByteSize(klass_offset) : in_ByteSize(receiver_offset)), in_ByteSize(lock_offset), oop_maps); + + if (is_critical_native) { + nm->set_lazy_critical_native(true); + } return nm; } @@ -2473,17 +2769,6 @@ static int fp_offset[ConcreteRegisterImpl::number_of_registers] = { 0 }; static bool offsets_initialized = false; -static VMRegPair reg64_to_VMRegPair(Register r) { - VMRegPair ret; - if (wordSize == 8) { - ret.set2(r->as_VMReg()); - } else { - ret.set_pair(r->successor()->as_VMReg(), r->as_VMReg()); - } - return ret; -} - - nmethod *SharedRuntime::generate_dtrace_nmethod( MacroAssembler *masm, methodHandle method) {
--- a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -44,7 +44,7 @@ #else define_pd_global(bool, ProfileInterpreter, true); #endif // CC_INTERP -define_pd_global(bool, TieredCompilation, true); +define_pd_global(bool, TieredCompilation, trueInTiered); define_pd_global(intx, CompileThreshold, 10000); define_pd_global(intx, BackEdgeThreshold, 100000);
--- a/hotspot/src/cpu/x86/vm/frame_x86.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -28,6 +28,7 @@ #include "oops/markOop.hpp" #include "oops/methodOop.hpp" #include "oops/oop.inline.hpp" +#include "prims/methodHandles.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp"
--- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -2364,23 +2364,19 @@ // grab another temp Register rsi_temp = rsi; - { if (rsi_temp == saved_last_sp) __ push(saved_last_sp); } - // (preceding push must be done after argslot address is taken!) -#define UNPUSH_RSI \ - { if (rsi_temp == saved_last_sp) __ pop(saved_last_sp); } // arx_argslot points both to the array and to the first output arg vmarg = Address(rax_argslot, 0); // Get the array value. - Register rsi_array = rsi_temp; + Register rdi_array = rdi_temp; Register rdx_array_klass = rdx_temp; BasicType elem_type = ek_adapter_opt_spread_type(ek); int elem_slots = type2size[elem_type]; // 1 or 2 int array_slots = 1; // array is always a T_OBJECT int length_offset = arrayOopDesc::length_offset_in_bytes(); int elem0_offset = arrayOopDesc::base_offset_in_bytes(elem_type); - __ movptr(rsi_array, vmarg); + __ movptr(rdi_array, vmarg); Label L_array_is_empty, L_insert_arg_space, L_copy_args, L_args_done; if (length_can_be_zero) { @@ -2391,12 +2387,30 @@ __ testl(rbx_temp, rbx_temp); __ jcc(Assembler::notZero, L_skip); } - __ testptr(rsi_array, rsi_array); - __ jcc(Assembler::zero, L_array_is_empty); + __ testptr(rdi_array, rdi_array); + __ jcc(Assembler::notZero, L_skip); + + // If 'rsi' contains the 'saved_last_sp' (this is only the + // case in a 32-bit version of the VM) we have to save 'rsi' + // on the stack because later on (at 'L_array_is_empty') 'rsi' + // will be overwritten. + { if (rsi_temp == saved_last_sp) __ push(saved_last_sp); } + // Also prepare a handy macro which restores 'rsi' if required. +#define UNPUSH_RSI \ + { if (rsi_temp == saved_last_sp) __ pop(saved_last_sp); } + + __ jmp(L_array_is_empty); __ bind(L_skip); } - __ null_check(rsi_array, oopDesc::klass_offset_in_bytes()); - __ load_klass(rdx_array_klass, rsi_array); + __ null_check(rdi_array, oopDesc::klass_offset_in_bytes()); + __ load_klass(rdx_array_klass, rdi_array); + + // Save 'rsi' if required (see comment above). Do this only + // after the null check such that the exception handler which is + // called in the case of a null pointer exception will not be + // confused by the extra value on the stack (it expects the + // return pointer on top of the stack) + { if (rsi_temp == saved_last_sp) __ push(saved_last_sp); } // Check the array type. Register rbx_klass = rbx_temp; @@ -2404,18 +2418,18 @@ load_klass_from_Class(_masm, rbx_klass); Label ok_array_klass, bad_array_klass, bad_array_length; - __ check_klass_subtype(rdx_array_klass, rbx_klass, rdi_temp, ok_array_klass); + __ check_klass_subtype(rdx_array_klass, rbx_klass, rsi_temp, ok_array_klass); // If we get here, the type check failed! __ jmp(bad_array_klass); __ BIND(ok_array_klass); // Check length. if (length_constant >= 0) { - __ cmpl(Address(rsi_array, length_offset), length_constant); + __ cmpl(Address(rdi_array, length_offset), length_constant); } else { Register rbx_vminfo = rbx_temp; load_conversion_vminfo(_masm, rbx_vminfo, rcx_amh_conversion); - __ cmpl(rbx_vminfo, Address(rsi_array, length_offset)); + __ cmpl(rbx_vminfo, Address(rdi_array, length_offset)); } __ jcc(Assembler::notEqual, bad_array_length); @@ -2427,9 +2441,9 @@ __ lea(rdx_argslot_limit, Address(rax_argslot, Interpreter::stackElementSize)); // 'stack_move' is negative number of words to insert // This number already accounts for elem_slots. - Register rdi_stack_move = rdi_temp; - load_stack_move(_masm, rdi_stack_move, rcx_recv, true); - __ cmpptr(rdi_stack_move, 0); + Register rsi_stack_move = rsi_temp; + load_stack_move(_masm, rsi_stack_move, rcx_recv, true); + __ cmpptr(rsi_stack_move, 0); assert(stack_move_unit() < 0, "else change this comparison"); __ jcc(Assembler::less, L_insert_arg_space); __ jcc(Assembler::equal, L_copy_args); @@ -2440,12 +2454,12 @@ __ jmp(L_args_done); // no spreading to do __ BIND(L_insert_arg_space); // come here in the usual case, stack_move < 0 (2 or more spread arguments) - Register rsi_temp = rsi_array; // spill this - insert_arg_slots(_masm, rdi_stack_move, - rax_argslot, rbx_temp, rsi_temp); + Register rdi_temp = rdi_array; // spill this + insert_arg_slots(_masm, rsi_stack_move, + rax_argslot, rbx_temp, rdi_temp); // reload the array since rsi was killed // reload from rdx_argslot_limit since rax_argslot is now decremented - __ movptr(rsi_array, Address(rdx_argslot_limit, -Interpreter::stackElementSize)); + __ movptr(rdi_array, Address(rdx_argslot_limit, -Interpreter::stackElementSize)); } else if (length_constant >= 1) { int new_slots = (length_constant * elem_slots) - array_slots; insert_arg_slots(_masm, new_slots * stack_move_unit(), @@ -2468,16 +2482,16 @@ if (length_constant == -1) { // [rax_argslot, rdx_argslot_limit) is the area we are inserting into. // Array element [0] goes at rdx_argslot_limit[-wordSize]. - Register rsi_source = rsi_array; - __ lea(rsi_source, Address(rsi_array, elem0_offset)); + Register rdi_source = rdi_array; + __ lea(rdi_source, Address(rdi_array, elem0_offset)); Register rdx_fill_ptr = rdx_argslot_limit; Label loop; __ BIND(loop); __ addptr(rdx_fill_ptr, -Interpreter::stackElementSize * elem_slots); move_typed_arg(_masm, elem_type, true, - Address(rdx_fill_ptr, 0), Address(rsi_source, 0), - rbx_temp, rdi_temp); - __ addptr(rsi_source, type2aelembytes(elem_type)); + Address(rdx_fill_ptr, 0), Address(rdi_source, 0), + rbx_temp, rsi_temp); + __ addptr(rdi_source, type2aelembytes(elem_type)); __ cmpptr(rdx_fill_ptr, rax_argslot); __ jcc(Assembler::above, loop); } else if (length_constant == 0) { @@ -2488,8 +2502,8 @@ for (int index = 0; index < length_constant; index++) { slot_offset -= Interpreter::stackElementSize * elem_slots; // fill backward move_typed_arg(_masm, elem_type, true, - Address(rax_argslot, slot_offset), Address(rsi_array, elem_offset), - rbx_temp, rdi_temp); + Address(rax_argslot, slot_offset), Address(rdi_array, elem_offset), + rbx_temp, rsi_temp); elem_offset += type2aelembytes(elem_type); } }
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -1091,12 +1091,238 @@ } } + +static void save_or_restore_arguments(MacroAssembler* masm, + const int stack_slots, + const int total_in_args, + const int arg_save_area, + OopMap* map, + VMRegPair* in_regs, + BasicType* in_sig_bt) { + // if map is non-NULL then the code should store the values, + // otherwise it should load them. + int handle_index = 0; + // Save down double word first + for ( int i = 0; i < total_in_args; i++) { + if (in_regs[i].first()->is_XMMRegister() && in_sig_bt[i] == T_DOUBLE) { + int slot = handle_index * VMRegImpl::slots_per_word + arg_save_area; + int offset = slot * VMRegImpl::stack_slot_size; + handle_index += 2; + assert(handle_index <= stack_slots, "overflow"); + if (map != NULL) { + __ movdbl(Address(rsp, offset), in_regs[i].first()->as_XMMRegister()); + } else { + __ movdbl(in_regs[i].first()->as_XMMRegister(), Address(rsp, offset)); + } + } + if (in_regs[i].first()->is_Register() && in_sig_bt[i] == T_LONG) { + int slot = handle_index * VMRegImpl::slots_per_word + arg_save_area; + int offset = slot * VMRegImpl::stack_slot_size; + handle_index += 2; + assert(handle_index <= stack_slots, "overflow"); + if (map != NULL) { + __ movl(Address(rsp, offset), in_regs[i].first()->as_Register()); + if (in_regs[i].second()->is_Register()) { + __ movl(Address(rsp, offset + 4), in_regs[i].second()->as_Register()); + } + } else { + __ movl(in_regs[i].first()->as_Register(), Address(rsp, offset)); + if (in_regs[i].second()->is_Register()) { + __ movl(in_regs[i].second()->as_Register(), Address(rsp, offset + 4)); + } + } + } + } + // Save or restore single word registers + for ( int i = 0; i < total_in_args; i++) { + if (in_regs[i].first()->is_Register()) { + int slot = handle_index++ * VMRegImpl::slots_per_word + arg_save_area; + int offset = slot * VMRegImpl::stack_slot_size; + assert(handle_index <= stack_slots, "overflow"); + if (in_sig_bt[i] == T_ARRAY && map != NULL) { + map->set_oop(VMRegImpl::stack2reg(slot));; + } + + // Value is in an input register pass we must flush it to the stack + const Register reg = in_regs[i].first()->as_Register(); + switch (in_sig_bt[i]) { + case T_ARRAY: + if (map != NULL) { + __ movptr(Address(rsp, offset), reg); + } else { + __ movptr(reg, Address(rsp, offset)); + } + break; + case T_BOOLEAN: + case T_CHAR: + case T_BYTE: + case T_SHORT: + case T_INT: + if (map != NULL) { + __ movl(Address(rsp, offset), reg); + } else { + __ movl(reg, Address(rsp, offset)); + } + break; + case T_OBJECT: + default: ShouldNotReachHere(); + } + } else if (in_regs[i].first()->is_XMMRegister()) { + if (in_sig_bt[i] == T_FLOAT) { + int slot = handle_index++ * VMRegImpl::slots_per_word + arg_save_area; + int offset = slot * VMRegImpl::stack_slot_size; + assert(handle_index <= stack_slots, "overflow"); + if (map != NULL) { + __ movflt(Address(rsp, offset), in_regs[i].first()->as_XMMRegister()); + } else { + __ movflt(in_regs[i].first()->as_XMMRegister(), Address(rsp, offset)); + } + } + } else if (in_regs[i].first()->is_stack()) { + if (in_sig_bt[i] == T_ARRAY && map != NULL) { + int offset_in_older_frame = in_regs[i].first()->reg2stack() + SharedRuntime::out_preserve_stack_slots(); + map->set_oop(VMRegImpl::stack2reg(offset_in_older_frame + stack_slots)); + } + } + } +} + +// Check GC_locker::needs_gc and enter the runtime if it's true. This +// keeps a new JNI critical region from starting until a GC has been +// forced. Save down any oops in registers and describe them in an +// OopMap. +static void check_needs_gc_for_critical_native(MacroAssembler* masm, + Register thread, + int stack_slots, + int total_c_args, + int total_in_args, + int arg_save_area, + OopMapSet* oop_maps, + VMRegPair* in_regs, + BasicType* in_sig_bt) { + __ block_comment("check GC_locker::needs_gc"); + Label cont; + __ cmp8(ExternalAddress((address)GC_locker::needs_gc_address()), false); + __ jcc(Assembler::equal, cont); + + // Save down any incoming oops and call into the runtime to halt for a GC + + OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); + + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, map, in_regs, in_sig_bt); + + address the_pc = __ pc(); + oop_maps->add_gc_map( __ offset(), map); + __ set_last_Java_frame(thread, rsp, noreg, the_pc); + + __ block_comment("block_for_jni_critical"); + __ push(thread); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::block_for_jni_critical))); + __ increment(rsp, wordSize); + + __ get_thread(thread); + __ reset_last_Java_frame(thread, false, true); + + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, NULL, in_regs, in_sig_bt); + + __ bind(cont); +#ifdef ASSERT + if (StressCriticalJNINatives) { + // Stress register saving + OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, map, in_regs, in_sig_bt); + // Destroy argument registers + for (int i = 0; i < total_in_args - 1; i++) { + if (in_regs[i].first()->is_Register()) { + const Register reg = in_regs[i].first()->as_Register(); + __ xorptr(reg, reg); + } else if (in_regs[i].first()->is_XMMRegister()) { + __ xorpd(in_regs[i].first()->as_XMMRegister(), in_regs[i].first()->as_XMMRegister()); + } else if (in_regs[i].first()->is_FloatRegister()) { + ShouldNotReachHere(); + } else if (in_regs[i].first()->is_stack()) { + // Nothing to do + } else { + ShouldNotReachHere(); + } + if (in_sig_bt[i] == T_LONG || in_sig_bt[i] == T_DOUBLE) { + i++; + } + } + + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, NULL, in_regs, in_sig_bt); + } +#endif +} + +// Unpack an array argument into a pointer to the body and the length +// if the array is non-null, otherwise pass 0 for both. +static void unpack_array_argument(MacroAssembler* masm, VMRegPair reg, BasicType in_elem_type, VMRegPair body_arg, VMRegPair length_arg) { + Register tmp_reg = rax; + assert(!body_arg.first()->is_Register() || body_arg.first()->as_Register() != tmp_reg, + "possible collision"); + assert(!length_arg.first()->is_Register() || length_arg.first()->as_Register() != tmp_reg, + "possible collision"); + + // Pass the length, ptr pair + Label is_null, done; + VMRegPair tmp(tmp_reg->as_VMReg()); + if (reg.first()->is_stack()) { + // Load the arg up from the stack + simple_move32(masm, reg, tmp); + reg = tmp; + } + __ testptr(reg.first()->as_Register(), reg.first()->as_Register()); + __ jccb(Assembler::equal, is_null); + __ lea(tmp_reg, Address(reg.first()->as_Register(), arrayOopDesc::base_offset_in_bytes(in_elem_type))); + simple_move32(masm, tmp, body_arg); + // load the length relative to the body. + __ movl(tmp_reg, Address(tmp_reg, arrayOopDesc::length_offset_in_bytes() - + arrayOopDesc::base_offset_in_bytes(in_elem_type))); + simple_move32(masm, tmp, length_arg); + __ jmpb(done); + __ bind(is_null); + // Pass zeros + __ xorptr(tmp_reg, tmp_reg); + simple_move32(masm, tmp, body_arg); + simple_move32(masm, tmp, length_arg); + __ bind(done); +} + + // --------------------------------------------------------------------------- // Generate a native wrapper for a given method. The method takes arguments // in the Java compiled code convention, marshals them to the native // convention (handlizes oops, etc), transitions to native, makes the call, // returns to java state (possibly blocking), unhandlizes any result and // returns. +// +// Critical native functions are a shorthand for the use of +// GetPrimtiveArrayCritical and disallow the use of any other JNI +// functions. The wrapper is expected to unpack the arguments before +// passing them to the callee and perform checks before and after the +// native call to ensure that they GC_locker +// lock_critical/unlock_critical semantics are followed. Some other +// parts of JNI setup are skipped like the tear down of the JNI handle +// block and the check for pending exceptions it's impossible for them +// to be thrown. +// +// They are roughly structured like this: +// if (GC_locker::needs_gc()) +// SharedRuntime::block_for_jni_critical(); +// tranistion to thread_in_native +// unpack arrray arguments and call native entry point +// check for safepoint in progress +// check if any thread suspend flags are set +// call into JVM and possible unlock the JNI critical +// if a GC was suppressed while in the critical native. +// transition back to thread_in_Java +// return to caller +// nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, methodHandle method, int compile_id, @@ -1105,6 +1331,13 @@ BasicType *in_sig_bt, VMRegPair *in_regs, BasicType ret_type) { + bool is_critical_native = true; + address native_func = method->critical_native_function(); + if (native_func == NULL) { + native_func = method->native_function(); + is_critical_native = false; + } + assert(native_func != NULL, "must have function"); // An OopMap for lock (and class if static) OopMapSet *oop_maps = new OopMapSet(); @@ -1115,30 +1348,72 @@ // we convert the java signature to a C signature by inserting // the hidden arguments as arg[0] and possibly arg[1] (static method) - int total_c_args = total_in_args + 1; - if (method->is_static()) { - total_c_args++; + int total_c_args = total_in_args; + if (!is_critical_native) { + total_c_args += 1; + if (method->is_static()) { + total_c_args++; + } + } else { + for (int i = 0; i < total_in_args; i++) { + if (in_sig_bt[i] == T_ARRAY) { + total_c_args++; + } + } } BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_c_args); - VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args); + VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args); + BasicType* in_elem_bt = NULL; int argc = 0; - out_sig_bt[argc++] = T_ADDRESS; - if (method->is_static()) { - out_sig_bt[argc++] = T_OBJECT; + if (!is_critical_native) { + out_sig_bt[argc++] = T_ADDRESS; + if (method->is_static()) { + out_sig_bt[argc++] = T_OBJECT; + } + + for (int i = 0; i < total_in_args ; i++ ) { + out_sig_bt[argc++] = in_sig_bt[i]; + } + } else { + Thread* THREAD = Thread::current(); + in_elem_bt = NEW_RESOURCE_ARRAY(BasicType, total_in_args); + SignatureStream ss(method->signature()); + for (int i = 0; i < total_in_args ; i++ ) { + if (in_sig_bt[i] == T_ARRAY) { + // Arrays are passed as int, elem* pair + out_sig_bt[argc++] = T_INT; + out_sig_bt[argc++] = T_ADDRESS; + Symbol* atype = ss.as_symbol(CHECK_NULL); + const char* at = atype->as_C_string(); + if (strlen(at) == 2) { + assert(at[0] == '[', "must be"); + switch (at[1]) { + case 'B': in_elem_bt[i] = T_BYTE; break; + case 'C': in_elem_bt[i] = T_CHAR; break; + case 'D': in_elem_bt[i] = T_DOUBLE; break; + case 'F': in_elem_bt[i] = T_FLOAT; break; + case 'I': in_elem_bt[i] = T_INT; break; + case 'J': in_elem_bt[i] = T_LONG; break; + case 'S': in_elem_bt[i] = T_SHORT; break; + case 'Z': in_elem_bt[i] = T_BOOLEAN; break; + default: ShouldNotReachHere(); + } + } + } else { + out_sig_bt[argc++] = in_sig_bt[i]; + in_elem_bt[i] = T_VOID; + } + if (in_sig_bt[i] != T_VOID) { + assert(in_sig_bt[i] == ss.type(), "must match"); + ss.next(); + } + } } - int i; - for (i = 0; i < total_in_args ; i++ ) { - out_sig_bt[argc++] = in_sig_bt[i]; - } - - // Now figure out where the args must be stored and how much stack space - // they require (neglecting out_preserve_stack_slots but space for storing - // the 1st six register arguments). It's weird see int_stk_helper. - // + // they require. int out_arg_slots; out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); @@ -1151,9 +1426,44 @@ int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots; // Now the space for the inbound oop handle area + int total_save_slots = 2 * VMRegImpl::slots_per_word; // 2 arguments passed in registers + if (is_critical_native) { + // Critical natives may have to call out so they need a save area + // for register arguments. + int double_slots = 0; + int single_slots = 0; + for ( int i = 0; i < total_in_args; i++) { + if (in_regs[i].first()->is_Register()) { + const Register reg = in_regs[i].first()->as_Register(); + switch (in_sig_bt[i]) { + case T_ARRAY: + case T_BOOLEAN: + case T_BYTE: + case T_SHORT: + case T_CHAR: + case T_INT: single_slots++; break; + case T_LONG: double_slots++; break; + default: ShouldNotReachHere(); + } + } else if (in_regs[i].first()->is_XMMRegister()) { + switch (in_sig_bt[i]) { + case T_FLOAT: single_slots++; break; + case T_DOUBLE: double_slots++; break; + default: ShouldNotReachHere(); + } + } else if (in_regs[i].first()->is_FloatRegister()) { + ShouldNotReachHere(); + } + } + total_save_slots = double_slots * 2 + single_slots; + // align the save area + if (double_slots != 0) { + stack_slots = round_to(stack_slots, 2); + } + } int oop_handle_offset = stack_slots; - stack_slots += 2*VMRegImpl::slots_per_word; + stack_slots += total_save_slots; // Now any space we need for handlizing a klass if static method @@ -1161,7 +1471,6 @@ int klass_offset = -1; int lock_slot_offset = 0; bool is_static = false; - int oop_temp_slot_offset = 0; if (method->is_static()) { klass_slot_offset = stack_slots; @@ -1221,7 +1530,7 @@ // First thing make an ic check to see if we should even be here // We are free to use all registers as temps without saving them and - // restoring them except rbp,. rbp, is the only callee save register + // restoring them except rbp. rbp is the only callee save register // as far as the interpreter and the compiler(s) are concerned. @@ -1230,7 +1539,6 @@ Label hit; Label exception_pending; - __ verify_oop(receiver); __ cmpptr(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes())); __ jcc(Assembler::equal, hit); @@ -1292,11 +1600,10 @@ // Generate a new frame for the wrapper. __ enter(); - // -2 because return address is already present and so is saved rbp, + // -2 because return address is already present and so is saved rbp __ subptr(rsp, stack_size - 2*wordSize); - // Frame is now completed as far a size and linkage. - + // Frame is now completed as far as size and linkage. int frame_complete = ((intptr_t)__ pc()) - start; // Calculate the difference between rsp and rbp,. We need to know it @@ -1319,7 +1626,6 @@ // Compute the rbp, offset for any slots used after the jni call int lock_slot_rbp_offset = (lock_slot_offset*VMRegImpl::stack_slot_size) - fp_adjustment; - int oop_temp_slot_rbp_offset = (oop_temp_slot_offset*VMRegImpl::stack_slot_size) - fp_adjustment; // We use rdi as a thread pointer because it is callee save and // if we load it once it is usable thru the entire wrapper @@ -1332,6 +1638,10 @@ __ get_thread(thread); + if (is_critical_native) { + check_needs_gc_for_critical_native(masm, thread, stack_slots, total_c_args, total_in_args, + oop_handle_offset, oop_maps, in_regs, in_sig_bt); + } // // We immediately shuffle the arguments so that any vm call we have to @@ -1353,7 +1663,7 @@ // vectors we have in our possession. We simply walk the java vector to // get the source locations and the c vector to get the destinations. - int c_arg = method->is_static() ? 2 : 1 ; + int c_arg = is_critical_native ? 0 : (method->is_static() ? 2 : 1 ); // Record rsp-based slot for receiver on stack for non-static methods int receiver_offset = -1; @@ -1373,10 +1683,16 @@ // Are free to temporaries if we have to do stack to steck moves. // All inbound args are referenced based on rbp, and all outbound args via rsp. - for (i = 0; i < total_in_args ; i++, c_arg++ ) { + for (int i = 0; i < total_in_args ; i++, c_arg++ ) { switch (in_sig_bt[i]) { case T_ARRAY: + if (is_critical_native) { + unpack_array_argument(masm, in_regs[i], in_elem_bt[i], out_regs[c_arg + 1], out_regs[c_arg]); + c_arg++; + break; + } case T_OBJECT: + assert(!is_critical_native, "no oop arguments"); object_move(masm, map, oop_handle_offset, stack_slots, in_regs[i], out_regs[c_arg], ((i == 0) && (!is_static)), &receiver_offset); @@ -1408,7 +1724,7 @@ // Pre-load a static method's oop into rsi. Used both by locking code and // the normal JNI call code. - if (method->is_static()) { + if (method->is_static() && !is_critical_native) { // load opp into a register __ movoop(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror())); @@ -1463,6 +1779,7 @@ // Lock a synchronized method if (method->is_synchronized()) { + assert(!is_critical_native, "unhandled"); const int mark_word_offset = BasicLock::displaced_header_offset_in_bytes(); @@ -1529,14 +1846,15 @@ // get JNIEnv* which is first argument to native - - __ lea(rdx, Address(thread, in_bytes(JavaThread::jni_environment_offset()))); - __ movptr(Address(rsp, 0), rdx); + if (!is_critical_native) { + __ lea(rdx, Address(thread, in_bytes(JavaThread::jni_environment_offset()))); + __ movptr(Address(rsp, 0), rdx); + } // Now set thread in native __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_native); - __ call(RuntimeAddress(method->native_function())); + __ call(RuntimeAddress(native_func)); // WARNING - on Windows Java Natives use pascal calling convention and pop the // arguments off of the stack. We could just re-adjust the stack pointer here @@ -1591,6 +1909,8 @@ __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); } + Label after_transition; + // check for safepoint operation in progress and/or pending suspend requests { Label Continue; @@ -1611,17 +1931,29 @@ // save_native_result(masm, ret_type, stack_slots); __ push(thread); - __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, - JavaThread::check_special_condition_for_native_trans))); + if (!is_critical_native) { + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, + JavaThread::check_special_condition_for_native_trans))); + } else { + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, + JavaThread::check_special_condition_for_native_trans_and_transition))); + } __ increment(rsp, wordSize); // Restore any method result value restore_native_result(masm, ret_type, stack_slots); + if (is_critical_native) { + // The call above performed the transition to thread_in_Java so + // skip the transition logic below. + __ jmpb(after_transition); + } + __ bind(Continue); } // change thread state __ movl(Address(thread, JavaThread::thread_state_offset()), _thread_in_Java); + __ bind(after_transition); Label reguard; Label reguard_done; @@ -1710,15 +2042,15 @@ __ verify_oop(rax); } - // reset handle block - __ movptr(rcx, Address(thread, JavaThread::active_handles_offset())); - - __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); - - // Any exception pending? - __ cmpptr(Address(thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD); - __ jcc(Assembler::notEqual, exception_pending); - + if (!is_critical_native) { + // reset handle block + __ movptr(rcx, Address(thread, JavaThread::active_handles_offset())); + __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), NULL_WORD); + + // Any exception pending? + __ cmpptr(Address(thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD); + __ jcc(Assembler::notEqual, exception_pending); + } // no exception, we're almost done @@ -1829,16 +2161,18 @@ // BEGIN EXCEPTION PROCESSING - // Forward the exception - __ bind(exception_pending); - - // remove possible return value from FPU register stack - __ empty_FPU_stack(); - - // pop our frame - __ leave(); - // and forward the exception - __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); + if (!is_critical_native) { + // Forward the exception + __ bind(exception_pending); + + // remove possible return value from FPU register stack + __ empty_FPU_stack(); + + // pop our frame + __ leave(); + // and forward the exception + __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); + } __ flush(); @@ -1851,6 +2185,11 @@ (is_static ? in_ByteSize(klass_offset) : in_ByteSize(receiver_offset)), in_ByteSize(lock_slot_offset*VMRegImpl::stack_slot_size), oop_maps); + + if (is_critical_native) { + nm->set_lazy_critical_native(true); + } + return nm; }
--- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -938,6 +938,25 @@ } } +static void move_ptr(MacroAssembler* masm, VMRegPair src, VMRegPair dst) { + if (src.first()->is_stack()) { + if (dst.first()->is_stack()) { + // stack to stack + __ movq(rax, Address(rbp, reg2offset_in(src.first()))); + __ movq(Address(rsp, reg2offset_out(dst.first())), rax); + } else { + // stack to reg + __ movq(dst.first()->as_Register(), Address(rbp, reg2offset_in(src.first()))); + } + } else if (dst.first()->is_stack()) { + // reg to stack + __ movq(Address(rsp, reg2offset_out(dst.first())), src.first()->as_Register()); + } else { + if (dst.first() != src.first()) { + __ movq(dst.first()->as_Register(), src.first()->as_Register()); + } + } +} // An oop arg. Must pass a handle not the oop itself static void object_move(MacroAssembler* masm, @@ -1152,6 +1171,203 @@ } } + +static void save_or_restore_arguments(MacroAssembler* masm, + const int stack_slots, + const int total_in_args, + const int arg_save_area, + OopMap* map, + VMRegPair* in_regs, + BasicType* in_sig_bt) { + // if map is non-NULL then the code should store the values, + // otherwise it should load them. + int handle_index = 0; + // Save down double word first + for ( int i = 0; i < total_in_args; i++) { + if (in_regs[i].first()->is_XMMRegister() && in_sig_bt[i] == T_DOUBLE) { + int slot = handle_index * VMRegImpl::slots_per_word + arg_save_area; + int offset = slot * VMRegImpl::stack_slot_size; + handle_index += 2; + assert(handle_index <= stack_slots, "overflow"); + if (map != NULL) { + __ movdbl(Address(rsp, offset), in_regs[i].first()->as_XMMRegister()); + } else { + __ movdbl(in_regs[i].first()->as_XMMRegister(), Address(rsp, offset)); + } + } + if (in_regs[i].first()->is_Register() && + (in_sig_bt[i] == T_LONG || in_sig_bt[i] == T_ARRAY)) { + int slot = handle_index * VMRegImpl::slots_per_word + arg_save_area; + int offset = slot * VMRegImpl::stack_slot_size; + handle_index += 2; + assert(handle_index <= stack_slots, "overflow"); + if (map != NULL) { + __ movq(Address(rsp, offset), in_regs[i].first()->as_Register()); + if (in_sig_bt[i] == T_ARRAY) { + map->set_oop(VMRegImpl::stack2reg(slot));; + } + } else { + __ movq(in_regs[i].first()->as_Register(), Address(rsp, offset)); + } + } + } + // Save or restore single word registers + for ( int i = 0; i < total_in_args; i++) { + if (in_regs[i].first()->is_Register()) { + int slot = handle_index++ * VMRegImpl::slots_per_word + arg_save_area; + int offset = slot * VMRegImpl::stack_slot_size; + assert(handle_index <= stack_slots, "overflow"); + + // Value is in an input register pass we must flush it to the stack + const Register reg = in_regs[i].first()->as_Register(); + switch (in_sig_bt[i]) { + case T_BOOLEAN: + case T_CHAR: + case T_BYTE: + case T_SHORT: + case T_INT: + if (map != NULL) { + __ movl(Address(rsp, offset), reg); + } else { + __ movl(reg, Address(rsp, offset)); + } + break; + case T_ARRAY: + case T_LONG: + // handled above + break; + case T_OBJECT: + default: ShouldNotReachHere(); + } + } else if (in_regs[i].first()->is_XMMRegister()) { + if (in_sig_bt[i] == T_FLOAT) { + int slot = handle_index++ * VMRegImpl::slots_per_word + arg_save_area; + int offset = slot * VMRegImpl::stack_slot_size; + assert(handle_index <= stack_slots, "overflow"); + if (map != NULL) { + __ movflt(Address(rsp, offset), in_regs[i].first()->as_XMMRegister()); + } else { + __ movflt(in_regs[i].first()->as_XMMRegister(), Address(rsp, offset)); + } + } + } else if (in_regs[i].first()->is_stack()) { + if (in_sig_bt[i] == T_ARRAY && map != NULL) { + int offset_in_older_frame = in_regs[i].first()->reg2stack() + SharedRuntime::out_preserve_stack_slots(); + map->set_oop(VMRegImpl::stack2reg(offset_in_older_frame + stack_slots)); + } + } + } +} + + +// Check GC_locker::needs_gc and enter the runtime if it's true. This +// keeps a new JNI critical region from starting until a GC has been +// forced. Save down any oops in registers and describe them in an +// OopMap. +static void check_needs_gc_for_critical_native(MacroAssembler* masm, + int stack_slots, + int total_c_args, + int total_in_args, + int arg_save_area, + OopMapSet* oop_maps, + VMRegPair* in_regs, + BasicType* in_sig_bt) { + __ block_comment("check GC_locker::needs_gc"); + Label cont; + __ cmp8(ExternalAddress((address)GC_locker::needs_gc_address()), false); + __ jcc(Assembler::equal, cont); + + // Save down any incoming oops and call into the runtime to halt for a GC + + OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, map, in_regs, in_sig_bt); + + address the_pc = __ pc(); + oop_maps->add_gc_map( __ offset(), map); + __ set_last_Java_frame(rsp, noreg, the_pc); + + __ block_comment("block_for_jni_critical"); + __ movptr(c_rarg0, r15_thread); + __ mov(r12, rsp); // remember sp + __ subptr(rsp, frame::arg_reg_save_area_bytes); // windows + __ andptr(rsp, -16); // align stack as required by ABI + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::block_for_jni_critical))); + __ mov(rsp, r12); // restore sp + __ reinit_heapbase(); + + __ reset_last_Java_frame(false, true); + + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, NULL, in_regs, in_sig_bt); + + __ bind(cont); +#ifdef ASSERT + if (StressCriticalJNINatives) { + // Stress register saving + OopMap* map = new OopMap(stack_slots * 2, 0 /* arg_slots*/); + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, map, in_regs, in_sig_bt); + // Destroy argument registers + for (int i = 0; i < total_in_args - 1; i++) { + if (in_regs[i].first()->is_Register()) { + const Register reg = in_regs[i].first()->as_Register(); + __ xorptr(reg, reg); + } else if (in_regs[i].first()->is_XMMRegister()) { + __ xorpd(in_regs[i].first()->as_XMMRegister(), in_regs[i].first()->as_XMMRegister()); + } else if (in_regs[i].first()->is_FloatRegister()) { + ShouldNotReachHere(); + } else if (in_regs[i].first()->is_stack()) { + // Nothing to do + } else { + ShouldNotReachHere(); + } + if (in_sig_bt[i] == T_LONG || in_sig_bt[i] == T_DOUBLE) { + i++; + } + } + + save_or_restore_arguments(masm, stack_slots, total_in_args, + arg_save_area, NULL, in_regs, in_sig_bt); + } +#endif +} + +// Unpack an array argument into a pointer to the body and the length +// if the array is non-null, otherwise pass 0 for both. +static void unpack_array_argument(MacroAssembler* masm, VMRegPair reg, BasicType in_elem_type, VMRegPair body_arg, VMRegPair length_arg) { + Register tmp_reg = rax; + assert(!body_arg.first()->is_Register() || body_arg.first()->as_Register() != tmp_reg, + "possible collision"); + assert(!length_arg.first()->is_Register() || length_arg.first()->as_Register() != tmp_reg, + "possible collision"); + + // Pass the length, ptr pair + Label is_null, done; + VMRegPair tmp; + tmp.set_ptr(tmp_reg->as_VMReg()); + if (reg.first()->is_stack()) { + // Load the arg up from the stack + move_ptr(masm, reg, tmp); + reg = tmp; + } + __ testptr(reg.first()->as_Register(), reg.first()->as_Register()); + __ jccb(Assembler::equal, is_null); + __ lea(tmp_reg, Address(reg.first()->as_Register(), arrayOopDesc::base_offset_in_bytes(in_elem_type))); + move_ptr(masm, tmp, body_arg); + // load the length relative to the body. + __ movl(tmp_reg, Address(tmp_reg, arrayOopDesc::length_offset_in_bytes() - + arrayOopDesc::base_offset_in_bytes(in_elem_type))); + move32_64(masm, tmp, length_arg); + __ jmpb(done); + __ bind(is_null); + // Pass zeros + __ xorptr(tmp_reg, tmp_reg); + move_ptr(masm, tmp, body_arg); + move32_64(masm, tmp, length_arg); + __ bind(done); +} + // --------------------------------------------------------------------------- // Generate a native wrapper for a given method. The method takes arguments // in the Java compiled code convention, marshals them to the native @@ -1166,10 +1382,14 @@ BasicType *in_sig_bt, VMRegPair *in_regs, BasicType ret_type) { - // Native nmethod wrappers never take possesion of the oop arguments. - // So the caller will gc the arguments. The only thing we need an - // oopMap for is if the call is static - // + bool is_critical_native = true; + address native_func = method->critical_native_function(); + if (native_func == NULL) { + native_func = method->native_function(); + is_critical_native = false; + } + assert(native_func != NULL, "must have function"); + // An OopMap for lock (and class if static) OopMapSet *oop_maps = new OopMapSet(); intptr_t start = (intptr_t)__ pc(); @@ -1180,27 +1400,72 @@ // we convert the java signature to a C signature by inserting // the hidden arguments as arg[0] and possibly arg[1] (static method) - int total_c_args = total_in_args + 1; - if (method->is_static()) { - total_c_args++; + int total_c_args = total_in_args; + if (!is_critical_native) { + total_c_args += 1; + if (method->is_static()) { + total_c_args++; + } + } else { + for (int i = 0; i < total_in_args; i++) { + if (in_sig_bt[i] == T_ARRAY) { + total_c_args++; + } + } } BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_c_args); - VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args); + VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_c_args); + BasicType* in_elem_bt = NULL; int argc = 0; - out_sig_bt[argc++] = T_ADDRESS; - if (method->is_static()) { - out_sig_bt[argc++] = T_OBJECT; - } - - for (int i = 0; i < total_in_args ; i++ ) { - out_sig_bt[argc++] = in_sig_bt[i]; + if (!is_critical_native) { + out_sig_bt[argc++] = T_ADDRESS; + if (method->is_static()) { + out_sig_bt[argc++] = T_OBJECT; + } + + for (int i = 0; i < total_in_args ; i++ ) { + out_sig_bt[argc++] = in_sig_bt[i]; + } + } else { + Thread* THREAD = Thread::current(); + in_elem_bt = NEW_RESOURCE_ARRAY(BasicType, total_in_args); + SignatureStream ss(method->signature()); + for (int i = 0; i < total_in_args ; i++ ) { + if (in_sig_bt[i] == T_ARRAY) { + // Arrays are passed as int, elem* pair + out_sig_bt[argc++] = T_INT; + out_sig_bt[argc++] = T_ADDRESS; + Symbol* atype = ss.as_symbol(CHECK_NULL); + const char* at = atype->as_C_string(); + if (strlen(at) == 2) { + assert(at[0] == '[', "must be"); + switch (at[1]) { + case 'B': in_elem_bt[i] = T_BYTE; break; + case 'C': in_elem_bt[i] = T_CHAR; break; + case 'D': in_elem_bt[i] = T_DOUBLE; break; + case 'F': in_elem_bt[i] = T_FLOAT; break; + case 'I': in_elem_bt[i] = T_INT; break; + case 'J': in_elem_bt[i] = T_LONG; break; + case 'S': in_elem_bt[i] = T_SHORT; break; + case 'Z': in_elem_bt[i] = T_BOOLEAN; break; + default: ShouldNotReachHere(); + } + } + } else { + out_sig_bt[argc++] = in_sig_bt[i]; + in_elem_bt[i] = T_VOID; + } + if (in_sig_bt[i] != T_VOID) { + assert(in_sig_bt[i] == ss.type(), "must match"); + ss.next(); + } + } } // Now figure out where the args must be stored and how much stack space // they require. - // int out_arg_slots; out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args); @@ -1213,13 +1478,47 @@ int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots; // Now the space for the inbound oop handle area + int total_save_slots = 6 * VMRegImpl::slots_per_word; // 6 arguments passed in registers + if (is_critical_native) { + // Critical natives may have to call out so they need a save area + // for register arguments. + int double_slots = 0; + int single_slots = 0; + for ( int i = 0; i < total_in_args; i++) { + if (in_regs[i].first()->is_Register()) { + const Register reg = in_regs[i].first()->as_Register(); + switch (in_sig_bt[i]) { + case T_ARRAY: + case T_BOOLEAN: + case T_BYTE: + case T_SHORT: + case T_CHAR: + case T_INT: single_slots++; break; + case T_LONG: double_slots++; break; + default: ShouldNotReachHere(); + } + } else if (in_regs[i].first()->is_XMMRegister()) { + switch (in_sig_bt[i]) { + case T_FLOAT: single_slots++; break; + case T_DOUBLE: double_slots++; break; + default: ShouldNotReachHere(); + } + } else if (in_regs[i].first()->is_FloatRegister()) { + ShouldNotReachHere(); + } + } + total_save_slots = double_slots * 2 + single_slots; + // align the save area + if (double_slots != 0) { + stack_slots = round_to(stack_slots, 2); + } + } int oop_handle_offset = stack_slots; - stack_slots += 6*VMRegImpl::slots_per_word; + stack_slots += total_save_slots; // Now any space we need for handlizing a klass if static method - int oop_temp_slot_offset = 0; int klass_slot_offset = 0; int klass_offset = -1; int lock_slot_offset = 0; @@ -1272,7 +1571,6 @@ int stack_size = stack_slots * VMRegImpl::stack_slot_size; - // First thing make an ic check to see if we should even be here // We are free to use all registers as temps without saving them and @@ -1283,22 +1581,22 @@ const Register ic_reg = rax; const Register receiver = j_rarg0; - Label ok; + Label hit; Label exception_pending; assert_different_registers(ic_reg, receiver, rscratch1); __ verify_oop(receiver); __ load_klass(rscratch1, receiver); __ cmpq(ic_reg, rscratch1); - __ jcc(Assembler::equal, ok); + __ jcc(Assembler::equal, hit); __ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub())); - __ bind(ok); - // Verified entry point must be aligned __ align(8); + __ bind(hit); + int vep_offset = ((intptr_t)__ pc()) - start; // The instruction at the verified entry point must be 5 bytes or longer @@ -1319,9 +1617,8 @@ // -2 because return address is already present and so is saved rbp __ subptr(rsp, stack_size - 2*wordSize); - // Frame is now completed as far as size and linkage. - - int frame_complete = ((intptr_t)__ pc()) - start; + // Frame is now completed as far as size and linkage. + int frame_complete = ((intptr_t)__ pc()) - start; #ifdef ASSERT { @@ -1341,7 +1638,10 @@ const Register oop_handle_reg = r14; - + if (is_critical_native) { + check_needs_gc_for_critical_native(masm, stack_slots, total_c_args, total_in_args, + oop_handle_offset, oop_maps, in_regs, in_sig_bt); + } // // We immediately shuffle the arguments so that any vm call we have to @@ -1390,9 +1690,36 @@ #endif /* ASSERT */ - + if (is_critical_native) { + // The mapping of Java and C arguments passed in registers are + // rotated by one, which helps when passing arguments to regular + // Java method but for critical natives that creates a cycle which + // can cause arguments to be killed before they are used. Break + // the cycle by moving the first argument into a temporary + // register. + for (int i = 0; i < total_c_args; i++) { + if (in_regs[i].first()->is_Register() && + in_regs[i].first()->as_Register() == rdi) { + __ mov(rbx, rdi); + in_regs[i].set1(rbx->as_VMReg()); + } + } + } + + // This may iterate in two different directions depending on the + // kind of native it is. The reason is that for regular JNI natives + // the incoming and outgoing registers are offset upwards and for + // critical natives they are offset down. int c_arg = total_c_args - 1; - for ( int i = total_in_args - 1; i >= 0 ; i--, c_arg-- ) { + int stride = -1; + int init = total_in_args - 1; + if (is_critical_native) { + // stride forwards + c_arg = 0; + stride = 1; + init = 0; + } + for (int i = init, count = 0; count < total_in_args; i += stride, c_arg += stride, count++ ) { #ifdef ASSERT if (in_regs[i].first()->is_Register()) { assert(!reg_destroyed[in_regs[i].first()->as_Register()->encoding()], "destroyed reg!"); @@ -1407,7 +1734,20 @@ #endif /* ASSERT */ switch (in_sig_bt[i]) { case T_ARRAY: + if (is_critical_native) { + unpack_array_argument(masm, in_regs[i], in_elem_bt[i], out_regs[c_arg + 1], out_regs[c_arg]); + c_arg++; +#ifdef ASSERT + if (out_regs[c_arg].first()->is_Register()) { + reg_destroyed[out_regs[c_arg].first()->as_Register()->encoding()] = true; + } else if (out_regs[c_arg].first()->is_XMMRegister()) { + freg_destroyed[out_regs[c_arg].first()->as_XMMRegister()->encoding()] = true; + } +#endif + break; + } case T_OBJECT: + assert(!is_critical_native, "no oop arguments"); object_move(masm, map, oop_handle_offset, stack_slots, in_regs[i], out_regs[c_arg], ((i == 0) && (!is_static)), &receiver_offset); @@ -1443,7 +1783,7 @@ // Pre-load a static method's oop into r14. Used both by locking code and // the normal JNI call code. - if (method->is_static()) { + if (method->is_static() && !is_critical_native) { // load oop into a register __ movoop(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror())); @@ -1509,6 +1849,7 @@ Label lock_done; if (method->is_synchronized()) { + assert(!is_critical_native, "unhandled"); const int mark_word_offset = BasicLock::displaced_header_offset_in_bytes(); @@ -1572,13 +1913,14 @@ // get JNIEnv* which is first argument to native - - __ lea(c_rarg0, Address(r15_thread, in_bytes(JavaThread::jni_environment_offset()))); + if (!is_critical_native) { + __ lea(c_rarg0, Address(r15_thread, in_bytes(JavaThread::jni_environment_offset()))); + } // Now set thread in native __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_native); - __ call(RuntimeAddress(method->native_function())); + __ call(RuntimeAddress(native_func)); // Either restore the MXCSR register after returning from the JNI Call // or verify that it wasn't changed. @@ -1634,6 +1976,7 @@ } } + Label after_transition; // check for safepoint operation in progress and/or pending suspend requests { @@ -1659,16 +2002,28 @@ __ mov(r12, rsp); // remember sp __ subptr(rsp, frame::arg_reg_save_area_bytes); // windows __ andptr(rsp, -16); // align stack as required by ABI - __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); + if (!is_critical_native) { + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); + } else { + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans_and_transition))); + } __ mov(rsp, r12); // restore sp __ reinit_heapbase(); // Restore any method result value restore_native_result(masm, ret_type, stack_slots); + + if (is_critical_native) { + // The call above performed the transition to thread_in_Java so + // skip the transition logic below. + __ jmpb(after_transition); + } + __ bind(Continue); } // change thread state __ movl(Address(r15_thread, JavaThread::thread_state_offset()), _thread_in_Java); + __ bind(after_transition); Label reguard; Label reguard_done; @@ -1746,17 +2101,21 @@ __ verify_oop(rax); } - // reset handle block - __ movptr(rcx, Address(r15_thread, JavaThread::active_handles_offset())); - __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); + if (!is_critical_native) { + // reset handle block + __ movptr(rcx, Address(r15_thread, JavaThread::active_handles_offset())); + __ movptr(Address(rcx, JNIHandleBlock::top_offset_in_bytes()), (int32_t)NULL_WORD); + } // pop our frame __ leave(); - // Any exception pending? - __ cmpptr(Address(r15_thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD); - __ jcc(Assembler::notEqual, exception_pending); + if (!is_critical_native) { + // Any exception pending? + __ cmpptr(Address(r15_thread, in_bytes(Thread::pending_exception_offset())), (int32_t)NULL_WORD); + __ jcc(Assembler::notEqual, exception_pending); + } // Return @@ -1764,12 +2123,13 @@ // Unexpected paths are out of line and go here - // forward the exception - __ bind(exception_pending); - - // and forward the exception - __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); - + if (!is_critical_native) { + // forward the exception + __ bind(exception_pending); + + // and forward the exception + __ jump(RuntimeAddress(StubRoutines::forward_exception_entry())); + } // Slow path locking & unlocking if (method->is_synchronized()) { @@ -1876,6 +2236,11 @@ (is_static ? in_ByteSize(klass_offset) : in_ByteSize(receiver_offset)), in_ByteSize(lock_slot_offset*VMRegImpl::stack_slot_size), oop_maps); + + if (is_critical_native) { + nm->set_lazy_critical_native(true); + } + return nm; }
--- a/hotspot/src/os/windows/vm/os_windows.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/os/windows/vm/os_windows.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -2088,7 +2088,6 @@ #elif _M_AMD64 PCONTEXT ctx = exceptionInfo->ContextRecord; address pc = (address)ctx->Rip; - NOT_PRODUCT(Events::log("idiv overflow exception at " INTPTR_FORMAT , pc)); assert(pc[0] == 0xF7, "not an idiv opcode"); assert((pc[1] & ~0x7) == 0xF8, "cannot handle non-register operands"); assert(ctx->Rax == min_jint, "unexpected idiv exception"); @@ -2100,7 +2099,6 @@ #else PCONTEXT ctx = exceptionInfo->ContextRecord; address pc = (address)ctx->Eip; - NOT_PRODUCT(Events::log("idiv overflow exception at " INTPTR_FORMAT , pc)); assert(pc[0] == 0xF7, "not an idiv opcode"); assert((pc[1] & ~0x7) == 0xF8, "cannot handle non-register operands"); assert(ctx->Eax == min_jint, "unexpected idiv exception"); @@ -5336,4 +5334,3 @@ } #endif -
--- a/hotspot/src/share/tools/ProjectCreator/BuildConfig.java Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/tools/ProjectCreator/BuildConfig.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -243,6 +243,7 @@ sysDefines.add("_WINDOWS"); sysDefines.add("HOTSPOT_BUILD_USER=\\\""+System.getProperty("user.name")+"\\\""); sysDefines.add("HOTSPOT_BUILD_TARGET=\\\""+get("Build")+"\\\""); + sysDefines.add("INCLUDE_TRACE"); sysDefines.add("_JNI_IMPLEMENTATION_"); if (vars.get("PlatformName").equals("Win32")) { sysDefines.add("HOTSPOT_LIB_ARCH=\\\"i386\\\"");
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -1592,6 +1592,7 @@ // this happened while running the JCK invokevirtual tests under doit. TKR ciMethod* cha_monomorphic_target = NULL; ciMethod* exact_target = NULL; + Value better_receiver = NULL; if (UseCHA && DeoptC1 && klass->is_loaded() && target->is_loaded() && !target->is_method_handle_invoke()) { Value receiver = NULL; @@ -1653,6 +1654,18 @@ ciInstanceKlass* singleton = NULL; if (target->holder()->nof_implementors() == 1) { singleton = target->holder()->implementor(0); + + assert(holder->is_interface(), "invokeinterface to non interface?"); + ciInstanceKlass* decl_interface = (ciInstanceKlass*)holder; + // the number of implementors for decl_interface is less or + // equal to the number of implementors for target->holder() so + // if number of implementors of target->holder() == 1 then + // number of implementors for decl_interface is 0 or 1. If + // it's 0 then no class implements decl_interface and there's + // no point in inlining. + if (!holder->is_loaded() || decl_interface->nof_implementors() != 1) { + singleton = NULL; + } } if (singleton) { cha_monomorphic_target = target->find_monomorphic_target(calling_klass, target->holder(), singleton); @@ -1667,7 +1680,9 @@ CheckCast* c = new CheckCast(klass, receiver, copy_state_for_exception()); c->set_incompatible_class_change_check(); c->set_direct_compare(klass->is_final()); - append_split(c); + // pass the result of the checkcast so that the compiler has + // more accurate type info in the inlinee + better_receiver = append_split(c); } } } @@ -1709,7 +1724,7 @@ } if (!success) { // static binding => check if callee is ok - success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL)); + success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL), better_receiver); } CHECK_BAILOUT(); @@ -3034,7 +3049,7 @@ } -bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known) { +bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known, Value receiver) { // Clear out any existing inline bailout condition clear_inline_bailout(); @@ -3056,7 +3071,7 @@ } else if (callee->is_abstract()) { INLINE_BAILOUT("abstract") } else { - return try_inline_full(callee, holder_known); + return try_inline_full(callee, holder_known, NULL, receiver); } } @@ -3405,7 +3420,7 @@ } -bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, BlockBegin* cont_block) { +bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, BlockBegin* cont_block, Value receiver) { assert(!callee->is_native(), "callee must not be native"); if (CompilationPolicy::policy()->should_not_inline(compilation()->env(), callee)) { INLINE_BAILOUT("inlining prohibited by policy"); @@ -3541,6 +3556,9 @@ Value arg = caller_state->stack_at_inc(i); // NOTE: take base() of arg->type() to avoid problems storing // constants + if (receiver != NULL && par_no == 0) { + arg = receiver; + } store_local(callee_state, arg, arg->type()->base(), par_no); } } @@ -3683,56 +3701,61 @@ // Get the two MethodHandle inputs from the Phi. Value op1 = phi->operand_at(0); Value op2 = phi->operand_at(1); - ciMethodHandle* mh1 = op1->type()->as_ObjectType()->constant_value()->as_method_handle(); - ciMethodHandle* mh2 = op2->type()->as_ObjectType()->constant_value()->as_method_handle(); - - // Set the callee to have access to the class and signature in - // the MethodHandleCompiler. - mh1->set_callee(callee); - mh1->set_caller(method()); - mh2->set_callee(callee); - mh2->set_caller(method()); - - // Get adapters for the MethodHandles. - ciMethod* mh1_adapter = mh1->get_method_handle_adapter(); - ciMethod* mh2_adapter = mh2->get_method_handle_adapter(); - - if (mh1_adapter != NULL && mh2_adapter != NULL) { - set_inline_cleanup_info(); - - // Build the If guard - BlockBegin* one = new BlockBegin(next_bci()); - BlockBegin* two = new BlockBegin(next_bci()); - BlockBegin* end = new BlockBegin(next_bci()); - Instruction* iff = append(new If(phi, If::eql, false, op1, one, two, NULL, false)); - block()->set_end(iff->as_BlockEnd()); - - // Connect up the states - one->merge(block()->end()->state()); - two->merge(block()->end()->state()); - - // Save the state for the second inlinee - ValueStack* state_before = copy_state_before(); - - // Parse first adapter - _last = _block = one; - if (!try_inline_full(mh1_adapter, /*holder_known=*/ true, end)) { - restore_inline_cleanup_info(); - block()->clear_end(); // remove appended iff - return false; + ObjectType* op1type = op1->type()->as_ObjectType(); + ObjectType* op2type = op2->type()->as_ObjectType(); + + if (op1type->is_constant() && op2type->is_constant()) { + ciMethodHandle* mh1 = op1type->constant_value()->as_method_handle(); + ciMethodHandle* mh2 = op2type->constant_value()->as_method_handle(); + + // Set the callee to have access to the class and signature in + // the MethodHandleCompiler. + mh1->set_callee(callee); + mh1->set_caller(method()); + mh2->set_callee(callee); + mh2->set_caller(method()); + + // Get adapters for the MethodHandles. + ciMethod* mh1_adapter = mh1->get_method_handle_adapter(); + ciMethod* mh2_adapter = mh2->get_method_handle_adapter(); + + if (mh1_adapter != NULL && mh2_adapter != NULL) { + set_inline_cleanup_info(); + + // Build the If guard + BlockBegin* one = new BlockBegin(next_bci()); + BlockBegin* two = new BlockBegin(next_bci()); + BlockBegin* end = new BlockBegin(next_bci()); + Instruction* iff = append(new If(phi, If::eql, false, op1, one, two, NULL, false)); + block()->set_end(iff->as_BlockEnd()); + + // Connect up the states + one->merge(block()->end()->state()); + two->merge(block()->end()->state()); + + // Save the state for the second inlinee + ValueStack* state_before = copy_state_before(); + + // Parse first adapter + _last = _block = one; + if (!try_inline_full(mh1_adapter, /*holder_known=*/ true, end, NULL)) { + restore_inline_cleanup_info(); + block()->clear_end(); // remove appended iff + return false; + } + + // Parse second adapter + _last = _block = two; + _state = state_before; + if (!try_inline_full(mh2_adapter, /*holder_known=*/ true, end, NULL)) { + restore_inline_cleanup_info(); + block()->clear_end(); // remove appended iff + return false; + } + + connect_to_end(end); + return true; } - - // Parse second adapter - _last = _block = two; - _state = state_before; - if (!try_inline_full(mh2_adapter, /*holder_known=*/ true, end)) { - restore_inline_cleanup_info(); - block()->clear_end(); // remove appended iff - return false; - } - - connect_to_end(end); - return true; } } }
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -337,9 +337,9 @@ void fill_sync_handler(Value lock, BlockBegin* sync_handler, bool default_handler = false); // inliners - bool try_inline( ciMethod* callee, bool holder_known); + bool try_inline( ciMethod* callee, bool holder_known, Value receiver = NULL); bool try_inline_intrinsics(ciMethod* callee); - bool try_inline_full( ciMethod* callee, bool holder_known, BlockBegin* cont_block = NULL); + bool try_inline_full( ciMethod* callee, bool holder_known, BlockBegin* cont_block, Value receiver); bool try_inline_jsr(int jsr_dest_bci); // JSR 292 support
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -597,7 +597,6 @@ JRT_ENTRY(void, Runtime1::throw_range_check_exception(JavaThread* thread, int index)) NOT_PRODUCT(_throw_range_check_exception_count++;) - Events::log("throw_range_check"); char message[jintAsStringSize]; sprintf(message, "%d", index); SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message); @@ -606,7 +605,6 @@ JRT_ENTRY(void, Runtime1::throw_index_exception(JavaThread* thread, int index)) NOT_PRODUCT(_throw_index_exception_count++;) - Events::log("throw_index"); char message[16]; sprintf(message, "%d", index); SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_IndexOutOfBoundsException(), message); @@ -804,11 +802,7 @@ // Note also that in the presence of inlining it is not guaranteed // that caller_method() == caller_code->method() - int bci = vfst.bci(); - - Events::log("patch_code @ " INTPTR_FORMAT , caller_frame.pc()); - Bytecodes::Code code = caller_method()->java_code_at(bci); #ifndef PRODUCT
--- a/hotspot/src/share/vm/c1/c1_ValueMap.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/c1/c1_ValueMap.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -125,6 +125,7 @@ // otherwise it is possible that they are not evaluated f->pin(Instruction::PinGlobalValueNumbering); } + assert(x->type()->tag() == f->type()->tag(), "should have same type"); return f;
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -359,7 +359,7 @@ case Bytecodes::_nop: break; case Bytecodes::_aconst_null: - state.apush(empty_map); + state.apush(unknown_obj); break; case Bytecodes::_iconst_m1: case Bytecodes::_iconst_0: @@ -392,6 +392,8 @@ if (tag.is_long() || tag.is_double()) { // Only longs and doubles use 2 stack slots. state.lpush(); + } else if (tag.basic_type() == T_OBJECT) { + state.apush(unknown_obj); } else { state.spush(); }
--- a/hotspot/src/share/vm/ci/ciEnv.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/ci/ciEnv.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -284,6 +284,20 @@ // Return state of appropriate compilability int compilable() { return _compilable; } + const char* retry_message() const { + switch (_compilable) { + case ciEnv::MethodCompilable_not_at_tier: + return "retry at different tier"; + case ciEnv::MethodCompilable_never: + return "not retryable"; + case ciEnv::MethodCompilable: + return NULL; + default: + ShouldNotReachHere(); + return NULL; + } + } + bool break_at_compile() { return _break_at_compile; } void set_break_at_compile(bool z) { _break_at_compile = z; }
--- a/hotspot/src/share/vm/classfile/dictionary.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/classfile/dictionary.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -618,7 +618,8 @@ ResourceMark rm; HandleMark hm; - tty->print_cr("Java system dictionary (classes=%d)", number_of_entries()); + tty->print_cr("Java system dictionary (table_size=%d, classes=%d)", + table_size(), number_of_entries()); tty->print_cr("^ indicates that initiating loader is different from " "defining loader");
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -64,6 +64,9 @@ int SystemDictionary::_number_of_modifications = 0; +int SystemDictionary::_sdgeneration = 0; +const int SystemDictionary::_primelist[_prime_array_size] = {1009,2017,4049,5051,10103, + 20201,40423,99991}; oop SystemDictionary::_system_loader_lock_obj = NULL; @@ -1178,8 +1181,8 @@ klassOop SystemDictionary::find_shared_class(Symbol* class_name) { if (shared_dictionary() != NULL) { - unsigned int d_hash = dictionary()->compute_hash(class_name, Handle()); - int d_index = dictionary()->hash_to_index(d_hash); + unsigned int d_hash = shared_dictionary()->compute_hash(class_name, Handle()); + int d_index = shared_dictionary()->hash_to_index(d_hash); return shared_dictionary()->find_shared_class(d_index, d_hash, class_name); } else { return NULL; @@ -1750,7 +1753,21 @@ placeholders()->oops_do(blk); } - +// Calculate a "good" systemdictionary size based +// on predicted or current loaded classes count +int SystemDictionary::calculate_systemdictionary_size(int classcount) { + int newsize = _old_default_sdsize; + if ((classcount > 0) && !DumpSharedSpaces) { + int desiredsize = classcount/_average_depth_goal; + for (newsize = _primelist[_sdgeneration]; _sdgeneration < _prime_array_size -1; + newsize = _primelist[++_sdgeneration]) { + if (desiredsize <= newsize) { + break; + } + } + } + return newsize; +} bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) { bool result = dictionary()->do_unloading(is_alive); constraints()->purge_loader_constraints(is_alive); @@ -1873,7 +1890,8 @@ // Allocate arrays assert(dictionary() == NULL, "SystemDictionary should only be initialized once"); - _dictionary = new Dictionary(_nof_buckets); + _sdgeneration = 0; + _dictionary = new Dictionary(calculate_systemdictionary_size(PredictedLoadedClassCount)); _placeholders = new PlaceholderTable(_nof_buckets); _number_of_modifications = 0; _loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -346,6 +346,8 @@ // loaders. Returns "true" iff something was unloaded. static bool do_unloading(BoolObjectClosure* is_alive); + static int calculate_systemdictionary_size(int loadedclasses); + // Applies "f->do_oop" to all root oops in the system dictionary. static void oops_do(OopClosure* f); @@ -538,12 +540,20 @@ _loader_constraint_size = 107, // number of entries in constraint table _resolution_error_size = 107, // number of entries in resolution error table _invoke_method_size = 139, // number of entries in invoke method table - _nof_buckets = 1009 // number of buckets in hash table + _nof_buckets = 1009, // number of buckets in hash table for placeholders + _old_default_sdsize = 1009, // backward compat for system dictionary size + _prime_array_size = 8, // array of primes for system dictionary size + _average_depth_goal = 3 // goal for lookup length }; // Static variables + // hashtable sizes for system dictionary to allow growth + // prime numbers for system dictionary size + static int _sdgeneration; + static const int _primelist[_prime_array_size]; + // Hashtable holding loaded classes. static Dictionary* _dictionary;
--- a/hotspot/src/share/vm/code/compiledIC.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/code/compiledIC.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -165,7 +165,6 @@ instruction_address(), method->print_value_string(), entry); } - Events::log("compiledIC " INTPTR_FORMAT " --> megamorphic " INTPTR_FORMAT, this, (address)method()); // We can't check this anymore. With lazy deopt we could have already // cleaned this IC entry before we even return. This is possible if // we ran out of space in the inline cache buffer trying to do the
--- a/hotspot/src/share/vm/code/nmethod.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/code/nmethod.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -462,6 +462,7 @@ _speculatively_disconnected = 0; _has_unsafe_access = 0; _has_method_handle_invokes = 0; + _lazy_critical_native = 0; _marked_for_deoptimization = 0; _lock_count = 0; _stack_traversal_mark = 0; @@ -704,7 +705,6 @@ xtty->tail("print_native_nmethod"); } } - Events::log("Create nmethod " INTPTR_FORMAT, this); } // For dtrace wrappers @@ -781,7 +781,6 @@ xtty->tail("print_dtrace_nmethod"); } } - Events::log("Create nmethod " INTPTR_FORMAT, this); } #endif // def HAVE_DTRACE_H @@ -889,13 +888,6 @@ if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) { print_nmethod(printnmethods); } - - // Note: Do not verify in here as the CodeCache_lock is - // taken which would conflict with the CompiledIC_lock - // which taken during the verification of call sites. - // (was bug - gri 10/25/99) - - Events::log("Create nmethod " INTPTR_FORMAT, this); } @@ -1386,7 +1378,7 @@ assert_locked_or_safepoint(CodeCache_lock); // completely deallocate this method - EventMark m("flushing nmethod " INTPTR_FORMAT " %s", this, ""); + Events::log(JavaThread::current(), "flushing nmethod " INTPTR_FORMAT, this); if (PrintMethodFlushing) { tty->print_cr("*flushing nmethod %3d/" INTPTR_FORMAT ". Live blobs:" UINT32_FORMAT "/Free CodeCache:" SIZE_FORMAT "Kb", _compile_id, this, CodeCache::nof_blobs(), CodeCache::unallocated_capacity()/1024);
--- a/hotspot/src/share/vm/code/nmethod.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/code/nmethod.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -175,6 +175,7 @@ // set during construction unsigned int _has_unsafe_access:1; // May fault due to unsafe access. unsigned int _has_method_handle_invokes:1; // Has this method MethodHandle invokes? + unsigned int _lazy_critical_native:1; // Lazy JNI critical native // Protected by Patching_lock unsigned char _state; // {alive, not_entrant, zombie, unloaded} @@ -430,7 +431,10 @@ void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; } bool is_speculatively_disconnected() const { return _speculatively_disconnected; } - void set_speculatively_disconnected(bool z) { _speculatively_disconnected = z; } + void set_speculatively_disconnected(bool z) { _speculatively_disconnected = z; } + + bool is_lazy_critical_native() const { return _lazy_critical_native; } + void set_lazy_critical_native(bool z) { _lazy_critical_native = z; } int comp_level() const { return _comp_level; }
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -44,6 +44,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/sweeper.hpp" #include "utilities/dtrace.hpp" +#include "utilities/events.hpp" #ifdef COMPILER1 #include "c1/c1_Compiler.hpp" #endif @@ -189,6 +190,43 @@ GrowableArray<CompilerThread*>* CompileBroker::_method_threads = NULL; +class CompilationLog : public StringEventLog { + public: + CompilationLog() : StringEventLog("Compilation events") { + } + + void log_compile(JavaThread* thread, CompileTask* task) { + StringLogMessage lm; + stringStream msg = lm.stream(); + // msg.time_stamp().update_to(tty->time_stamp().ticks()); + task->print_compilation(&msg, true); + log(thread, "%s", (const char*)lm); + } + + void log_nmethod(JavaThread* thread, nmethod* nm) { + log(thread, "nmethod " INTPTR_FORMAT " code ["INTPTR_FORMAT ", " INTPTR_FORMAT "]", + nm, nm->code_begin(), nm->code_end()); + } + + void log_failure(JavaThread* thread, CompileTask* task, const char* reason, const char* retry_message) { + StringLogMessage lm; + lm.print("%4d COMPILE SKIPPED: %s", task->compile_id(), reason); + if (retry_message != NULL) { + lm.append(" (%s)", retry_message); + } + lm.print("\n"); + log(thread, "%s", (const char*)lm); + } +}; + +static CompilationLog* _compilation_log = NULL; + +void compileBroker_init() { + if (LogEvents) { + _compilation_log = new CompilationLog(); + } +} + CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) { CompilerThread* thread = CompilerThread::current(); thread->set_task(task); @@ -326,8 +364,12 @@ // ------------------------------------------------------------------ // CompileTask::print_compilation_impl -void CompileTask::print_compilation_impl(outputStream* st, methodOop method, int compile_id, int comp_level, bool is_osr_method, int osr_bci, bool is_blocking, const char* msg) { - st->print("%7d ", (int) st->time_stamp().milliseconds()); // print timestamp +void CompileTask::print_compilation_impl(outputStream* st, methodOop method, int compile_id, int comp_level, + bool is_osr_method, int osr_bci, bool is_blocking, + const char* msg, bool short_form) { + if (!short_form) { + st->print("%7d ", (int) st->time_stamp().milliseconds()); // print timestamp + } st->print("%4d ", compile_id); // print compilation number // For unloaded methods the transition to zombie occurs after the @@ -370,7 +412,9 @@ if (msg != NULL) { st->print(" %s", msg); } - st->cr(); + if (!short_form) { + st->cr(); + } } // ------------------------------------------------------------------ @@ -426,12 +470,12 @@ // ------------------------------------------------------------------ // CompileTask::print_compilation -void CompileTask::print_compilation(outputStream* st) { +void CompileTask::print_compilation(outputStream* st, bool short_form) { oop rem = JNIHandles::resolve(method_handle()); assert(rem != NULL && rem->is_method(), "must be"); methodOop method = (methodOop) rem; bool is_osr_method = osr_bci() != InvocationEntryBci; - print_compilation_impl(st, method, compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking()); + print_compilation_impl(st, method, compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), NULL, short_form); } // ------------------------------------------------------------------ @@ -1649,6 +1693,10 @@ CompilerThread* thread = CompilerThread::current(); ResourceMark rm(thread); + if (LogEvents) { + _compilation_log->log_compile(thread, task); + } + // Common flags. uint compile_id = task->compile_id(); int osr_bci = task->osr_bci(); @@ -1717,22 +1765,30 @@ ci_env.record_method_not_compilable("compile failed", !TieredCompilation); } + // Copy this bit to the enclosing block: + compilable = ci_env.compilable(); + if (ci_env.failing()) { - // Copy this bit to the enclosing block: - compilable = ci_env.compilable(); + const char* retry_message = ci_env.retry_message(); + if (_compilation_log != NULL) { + _compilation_log->log_failure(thread, task, ci_env.failure_reason(), retry_message); + } if (PrintCompilation) { - const char* reason = ci_env.failure_reason(); - if (compilable == ciEnv::MethodCompilable_not_at_tier) { - tty->print_cr("%4d COMPILE SKIPPED: %s (retry at different tier)", compile_id, reason); - } else if (compilable == ciEnv::MethodCompilable_never) { - tty->print_cr("%4d COMPILE SKIPPED: %s (not retryable)", compile_id, reason); - } else if (compilable == ciEnv::MethodCompilable) { - tty->print_cr("%4d COMPILE SKIPPED: %s", compile_id, reason); + tty->print("%4d COMPILE SKIPPED: %s", compile_id, ci_env.failure_reason()); + if (retry_message != NULL) { + tty->print(" (%s)", retry_message); } + tty->cr(); } } else { task->mark_success(); task->set_num_inlined_bytecodes(ci_env.num_inlined_bytecodes()); + if (_compilation_log != NULL) { + nmethod* code = task->code(); + if (code != NULL) { + _compilation_log->log_nmethod(thread, code); + } + } } } pop_jni_handle_block();
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/compiler/compileBroker.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -98,12 +98,16 @@ void set_prev(CompileTask* prev) { _prev = prev; } private: - static void print_compilation_impl(outputStream* st, methodOop method, int compile_id, int comp_level, bool is_osr_method = false, int osr_bci = -1, bool is_blocking = false, const char* msg = NULL); + static void print_compilation_impl(outputStream* st, methodOop method, int compile_id, int comp_level, + bool is_osr_method = false, int osr_bci = -1, bool is_blocking = false, + const char* msg = NULL, bool short_form = false); public: - void print_compilation(outputStream* st = tty); + void print_compilation(outputStream* st = tty, bool short_form = false); static void print_compilation(outputStream* st, const nmethod* nm, const char* msg = NULL) { - print_compilation_impl(st, nm->method(), nm->compile_id(), nm->comp_level(), nm->is_osr_method(), nm->is_osr_method() ? nm->osr_entry_bci() : -1, /*is_blocking*/ false, msg); + print_compilation_impl(st, nm->method(), nm->compile_id(), nm->comp_level(), + nm->is_osr_method(), nm->is_osr_method() ? nm->osr_entry_bci() : -1, /*is_blocking*/ false, + msg); } static void print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg = NULL);
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -5594,6 +5594,7 @@ GenCollectedHeap::StrongRootsScope srs(gch); workers->run_task(&tsk); } else { + ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), false); GenCollectedHeap::StrongRootsScope srs(gch); tsk.work(0); } @@ -5608,6 +5609,8 @@ ResourceMark rm; HandleMark hm; GenCollectedHeap* gch = GenCollectedHeap::heap(); + ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), false); + MarkRefsIntoAndScanClosure mrias_cl(_span, ref_processor(), &_markBitMap, &_modUnionTable, &_markStack, &_revisitStack, this,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1238,9 +1238,7 @@ SvcGCMarker sgcm(SvcGCMarker::FULL); ResourceMark rm; - if (PrintHeapAtGC) { - Universe::print_heap_before_gc(); - } + print_heap_before_gc(); HRSPhaseSetter x(HRSPhaseFullGC); verify_region_sets_optional(); @@ -1492,9 +1490,7 @@ _hrs.verify_optional(); verify_region_sets_optional(); - if (PrintHeapAtGC) { - Universe::print_heap_after_gc(); - } + print_heap_after_gc(); g1mm()->update_sizes(); post_full_gc_dump(); @@ -3560,9 +3556,7 @@ SvcGCMarker sgcm(SvcGCMarker::MINOR); ResourceMark rm; - if (PrintHeapAtGC) { - Universe::print_heap_before_gc(); - } + print_heap_before_gc(); HRSPhaseSetter x(HRSPhaseEvacuation); verify_region_sets_optional(); @@ -3937,9 +3931,7 @@ TASKQUEUE_STATS_ONLY(if (ParallelGCVerbose) print_taskqueue_stats()); TASKQUEUE_STATS_ONLY(reset_taskqueue_stats()); - if (PrintHeapAtGC) { - Universe::print_heap_after_gc(); - } + print_heap_after_gc(); g1mm()->update_sizes(); if (G1SummarizeRSetStats &&
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -126,7 +126,6 @@ void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading, bool clear_all_softrefs) { // Recursively traverse all live objects and mark them - EventMark m("1 mark object"); TraceTime tm("phase 1", PrintGC && Verbose, true, gclog_or_tty); GenMarkSweep::trace(" 1"); @@ -292,7 +291,6 @@ G1CollectedHeap* g1h = G1CollectedHeap::heap(); Generation* pg = g1h->perm_gen(); - EventMark m("2 compute new addresses"); TraceTime tm("phase 2", PrintGC && Verbose, true, gclog_or_tty); GenMarkSweep::trace("2"); @@ -337,7 +335,6 @@ Generation* pg = g1h->perm_gen(); // Adjust the pointers to reflect the new locations - EventMark m("3 adjust pointers"); TraceTime tm("phase 3", PrintGC && Verbose, true, gclog_or_tty); GenMarkSweep::trace("3"); @@ -402,7 +399,6 @@ G1CollectedHeap* g1h = G1CollectedHeap::heap(); Generation* pg = g1h->perm_gen(); - EventMark m("4 compact heap"); TraceTime tm("phase 4", PrintGC && Verbose, true, gclog_or_tty); GenMarkSweep::trace("4");
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -132,9 +132,7 @@ AdaptiveSizePolicyOutput(size_policy, heap->total_collections()); - if (PrintHeapAtGC) { - Universe::print_heap_before_gc(); - } + heap->print_heap_before_gc(); // Fill in TLABs heap->accumulate_statistics_all_tlabs(); @@ -377,9 +375,7 @@ NOT_PRODUCT(ref_processor()->verify_no_references_recorded()); - if (PrintHeapAtGC) { - Universe::print_heap_after_gc(); - } + heap->print_heap_after_gc(); heap->post_full_gc_dump(); @@ -504,7 +500,6 @@ void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) { // Recursively traverse all live objects and mark them - EventMark m("1 mark object"); TraceTime tm("phase 1", PrintGCDetails && Verbose, true, gclog_or_tty); trace(" 1"); @@ -563,7 +558,6 @@ void PSMarkSweep::mark_sweep_phase2() { - EventMark m("2 compute new addresses"); TraceTime tm("phase 2", PrintGCDetails && Verbose, true, gclog_or_tty); trace("2"); @@ -608,7 +602,6 @@ void PSMarkSweep::mark_sweep_phase3() { // Adjust the pointers to reflect the new locations - EventMark m("3 adjust pointers"); TraceTime tm("phase 3", PrintGCDetails && Verbose, true, gclog_or_tty); trace("3");
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -983,9 +983,7 @@ // We need to track unique mark sweep invocations as well. _total_invocations++; - if (PrintHeapAtGC) { - Universe::print_heap_before_gc(); - } + heap->print_heap_before_gc(); // Fill in TLABs heap->accumulate_statistics_all_tlabs(); @@ -1838,7 +1836,6 @@ void PSParallelCompact::summary_phase(ParCompactionManager* cm, bool maximum_compaction) { - EventMark m("2 summarize"); TraceTime tm("summary phase", print_phases(), true, gclog_or_tty); // trace("2"); @@ -2237,9 +2234,7 @@ collection_exit.update(); - if (PrintHeapAtGC) { - Universe::print_heap_after_gc(); - } + heap->print_heap_after_gc(); if (PrintGCTaskTimeStamps) { gclog_or_tty->print_cr("VM-Thread " INT64_FORMAT " " INT64_FORMAT " " INT64_FORMAT, @@ -2352,7 +2347,6 @@ void PSParallelCompact::marking_phase(ParCompactionManager* cm, bool maximum_heap_compaction) { // Recursively traverse all live objects and mark them - EventMark m("1 mark object"); TraceTime tm("marking phase", print_phases(), true, gclog_or_tty); ParallelScavengeHeap* heap = gc_heap(); @@ -2438,7 +2432,6 @@ void PSParallelCompact::adjust_roots() { // Adjust the pointers to reflect the new locations - EventMark m("3 adjust roots"); TraceTime tm("adjust roots", print_phases(), true, gclog_or_tty); // General strong roots. @@ -2469,7 +2462,6 @@ } void PSParallelCompact::compact_perm(ParCompactionManager* cm) { - EventMark m("4 compact perm"); TraceTime tm("compact perm gen", print_phases(), true, gclog_or_tty); // trace("4"); @@ -2647,7 +2639,6 @@ } void PSParallelCompact::compact() { - EventMark m("5 compact"); // trace("5"); TraceTime tm("compaction phase", print_phases(), true, gclog_or_tty); @@ -3502,4 +3493,3 @@ _updated_int_array_klass_obj = (klassOop) summary_data().calc_new_pointer(Universe::intArrayKlassObj()); } -
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 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 @@ -295,9 +295,7 @@ heap->record_gen_tops_before_GC(); } - if (PrintHeapAtGC) { - Universe::print_heap_before_gc(); - } + heap->print_heap_before_gc(); assert(!NeverTenure || _tenuring_threshold == markOopDesc::max_age + 1, "Sanity"); assert(!AlwaysTenure || _tenuring_threshold == 0, "Sanity"); @@ -643,9 +641,7 @@ Universe::verify(false); } - if (PrintHeapAtGC) { - Universe::print_heap_after_gc(); - } + heap->print_heap_after_gc(); if (ZapUnusedHeapArea) { young_gen->eden_space()->check_mangled_unused_area_complete();
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -51,6 +51,31 @@ size_t CollectedHeap::_filler_array_max_size = 0; +template <> +void EventLogBase<GCMessage>::print(outputStream* st, GCMessage& m) { + st->print_cr("GC heap %s", m.is_before ? "before" : "after"); + st->print_raw(m); +} + +void GCHeapLog::log_heap(bool before) { + if (!should_log()) { + return; + } + + jlong timestamp = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; + MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag); + int index = compute_log_index(); + _records[index].thread = NULL; // Its the GC thread so it's not that interesting. + _records[index].timestamp = timestamp; + _records[index].data.is_before = before; + stringStream st(_records[index].data.buffer(), _records[index].data.size()); + if (before) { + Universe::print_heap_before_gc(&st); + } else { + Universe::print_heap_after_gc(&st); + } +} + // Memory state functions. @@ -81,6 +106,12 @@ 80, GCCause::to_string(_gc_lastcause), CHECK); } _defer_initial_card_mark = false; // strengthened by subclass in pre_initialize() below. + // Create the ring log + if (LogEvents) { + _gc_heap_log = new GCHeapLog(); + } else { + _gc_heap_log = NULL; + } } void CollectedHeap::pre_initialize() {
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -31,6 +31,7 @@ #include "runtime/handles.hpp" #include "runtime/perfData.hpp" #include "runtime/safepoint.hpp" +#include "utilities/events.hpp" // A "CollectedHeap" is an implementation of a java heap for HotSpot. This // is an abstract class: there may be many different kinds of heaps. This @@ -43,6 +44,29 @@ class Thread; class CollectorPolicy; +class GCMessage : public FormatBuffer<1024> { + public: + bool is_before; + + public: + GCMessage() {} +}; + +class GCHeapLog : public EventLogBase<GCMessage> { + private: + void log_heap(bool before); + + public: + GCHeapLog() : EventLogBase<GCMessage>("GC Heap History") {} + + void log_heap_before() { + log_heap(true); + } + void log_heap_after() { + log_heap(false); + } +}; + // // CollectedHeap // SharedHeap @@ -62,6 +86,8 @@ // Used for filler objects (static, but initialized in ctor). static size_t _filler_array_max_size; + GCHeapLog* _gc_heap_log; + // Used in support of ReduceInitialCardMarks; only consulted if COMPILER2 is being used bool _defer_initial_card_mark; @@ -618,6 +644,27 @@ // Default implementation does nothing. virtual void print_tracing_info() const = 0; + // If PrintHeapAtGC is set call the appropriate routi + void print_heap_before_gc() { + if (PrintHeapAtGC) { + Universe::print_heap_before_gc(); + } + if (_gc_heap_log != NULL) { + _gc_heap_log->log_heap_before(); + } + } + void print_heap_after_gc() { + if (PrintHeapAtGC) { + Universe::print_heap_after_gc(); + } + if (_gc_heap_log != NULL) { + _gc_heap_log->log_heap_after(); + } + } + + // Allocate GCHeapLog during VM startup + static void initialize_heap_log(); + // Heap verification virtual void verify(bool allow_dirty, bool silent, VerifyOption option) = 0;
--- a/hotspot/src/share/vm/memory/gcLocker.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/memory/gcLocker.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -31,38 +31,93 @@ volatile jint GC_locker::_lock_count = 0; volatile bool GC_locker::_needs_gc = false; volatile bool GC_locker::_doing_gc = false; +jlong GC_locker::_wait_begin = 0; + +#ifdef ASSERT +volatile jint GC_locker::_debug_jni_lock_count = 0; +#endif + + +#ifdef ASSERT +void GC_locker::verify_critical_count() { + if (SafepointSynchronize::is_at_safepoint()) { + assert(!needs_gc() || _debug_jni_lock_count == _jni_lock_count, "must agree"); + int count = 0; + // Count the number of threads with critical operations in progress + for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) { + if (thr->in_critical()) { + count++; + } + } + if (_jni_lock_count != count) { + tty->print_cr("critical counts don't match: %d != %d", _jni_lock_count, count); + for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) { + if (thr->in_critical()) { + tty->print_cr(INTPTR_FORMAT " in_critical %d", thr, thr->in_critical()); + } + } + } + assert(_jni_lock_count == count, "must be equal"); + } +} +#endif + +bool GC_locker::check_active_before_gc() { + assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint"); + if (is_active() && !_needs_gc) { + verify_critical_count(); + _needs_gc = true; + if (PrintJNIGCStalls && PrintGCDetails) { + ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 + _wait_begin = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; + gclog_or_tty->print_cr(INT64_FORMAT ": Setting _needs_gc. Thread \"%s\" %d locked.", + _wait_begin, Thread::current()->name(), _jni_lock_count); + } + + } + return is_active(); +} void GC_locker::stall_until_clear() { assert(!JavaThread::current()->in_critical(), "Would deadlock"); - if (PrintJNIGCStalls && PrintGCDetails) { - ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 - gclog_or_tty->print_cr( - "Allocation failed. Thread \"%s\" is stalled by JNI critical section.", - JavaThread::current()->name()); + MutexLocker ml(JNICritical_lock); + + if (needs_gc()) { + if (PrintJNIGCStalls && PrintGCDetails) { + ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 + gclog_or_tty->print_cr(INT64_FORMAT ": Allocation failed. Thread \"%s\" is stalled by JNI critical section, %d locked.", + (os::javaTimeNanos() / NANOSECS_PER_MILLISEC) - _wait_begin, Thread::current()->name(), _jni_lock_count); + } } - MutexLocker ml(JNICritical_lock); + // Wait for _needs_gc to be cleared - while (GC_locker::needs_gc()) { + while (needs_gc()) { JNICritical_lock->wait(); } } -void GC_locker::jni_lock_slow() { +void GC_locker::jni_lock(JavaThread* thread) { + assert(!thread->in_critical(), "shouldn't currently be in a critical region"); MutexLocker mu(JNICritical_lock); // Block entering threads if we know at least one thread is in a // JNI critical region and we need a GC. // We check that at least one thread is in a critical region before // blocking because blocked threads are woken up by a thread exiting // a JNI critical region. - while ((is_jni_active() && needs_gc()) || _doing_gc) { + while ((needs_gc() && is_jni_active()) || _doing_gc) { JNICritical_lock->wait(); } - jni_lock(); + thread->enter_critical(); + _jni_lock_count++; + increment_debug_jni_lock_count(); } -void GC_locker::jni_unlock_slow() { +void GC_locker::jni_unlock(JavaThread* thread) { + assert(thread->in_last_critical(), "should be exiting critical region"); MutexLocker mu(JNICritical_lock); - jni_unlock(); + _jni_lock_count--; + decrement_debug_jni_lock_count(); + thread->exit_critical(); if (needs_gc() && !is_jni_active()) { // We're the last thread out. Cause a GC to occur. // GC will also check is_active, so this check is not @@ -74,11 +129,17 @@ { // Must give up the lock while at a safepoint MutexUnlocker munlock(JNICritical_lock); + if (PrintJNIGCStalls && PrintGCDetails) { + ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 + gclog_or_tty->print_cr(INT64_FORMAT ": Thread \"%s\" is performing GC after exiting critical section, %d locked", + (os::javaTimeNanos() / NANOSECS_PER_MILLISEC) - _wait_begin, Thread::current()->name(), _jni_lock_count); + } Universe::heap()->collect(GCCause::_gc_locker); } _doing_gc = false; } - clear_needs_gc(); + + _needs_gc = false; JNICritical_lock->notify_all(); } }
--- a/hotspot/src/share/vm/memory/gcLocker.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/memory/gcLocker.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -51,53 +51,70 @@ class GC_locker: public AllStatic { private: - static volatile jint _jni_lock_count; // number of jni active instances + // The _jni_lock_count keeps track of the number of threads that are + // currently in a critical region. It's only kept up to date when + // _needs_gc is true. The current value is computed during + // safepointing and decremented during the slow path of GC_locker + // unlocking. + static volatile jint _jni_lock_count; // number of jni active instances. + static volatile jint _lock_count; // number of other active instances static volatile bool _needs_gc; // heap is filling, we need a GC // note: bool is typedef'd as jint static volatile bool _doing_gc; // unlock_critical() is doing a GC + static jlong _wait_begin; // Timestamp for the setting of _needs_gc. + // Used only by printing code. + +#ifdef ASSERT + // This lock count is updated for all operations and is used to + // validate the jni_lock_count that is computed during safepoints. + static volatile jint _debug_jni_lock_count; +#endif + // Accessors static bool is_jni_active() { + assert(_needs_gc, "only valid when _needs_gc is set"); return _jni_lock_count > 0; } - static void set_needs_gc() { - assert(SafepointSynchronize::is_at_safepoint(), - "needs_gc is only set at a safepoint"); - _needs_gc = true; - } + // At a safepoint, visit all threads and count the number of active + // critical sections. This is used to ensure that all active + // critical sections are exited before a new one is started. + static void verify_critical_count() NOT_DEBUG_RETURN; - static void clear_needs_gc() { - assert_lock_strong(JNICritical_lock); - _needs_gc = false; - } - - static void jni_lock() { - Atomic::inc(&_jni_lock_count); - CHECK_UNHANDLED_OOPS_ONLY( - if (CheckUnhandledOops) { Thread::current()->_gc_locked_out_count++; }) - assert(Universe::heap() == NULL || !Universe::heap()->is_gc_active(), - "locking failed"); - } - - static void jni_unlock() { - Atomic::dec(&_jni_lock_count); - CHECK_UNHANDLED_OOPS_ONLY( - if (CheckUnhandledOops) { Thread::current()->_gc_locked_out_count--; }) - } - - static void jni_lock_slow(); - static void jni_unlock_slow(); + static void jni_lock(JavaThread* thread); + static void jni_unlock(JavaThread* thread); public: // Accessors static bool is_active(); static bool needs_gc() { return _needs_gc; } + // Shorthand - static bool is_active_and_needs_gc() { return is_active() && needs_gc();} + static bool is_active_and_needs_gc() { return needs_gc() && is_active(); } - // Calls set_needs_gc() if is_active() is true. Returns is_active(). + // In debug mode track the locking state at all times + static void increment_debug_jni_lock_count() { +#ifdef ASSERT + assert(_debug_jni_lock_count >= 0, "bad value"); + Atomic::inc(&_debug_jni_lock_count); +#endif + } + static void decrement_debug_jni_lock_count() { +#ifdef ASSERT + assert(_debug_jni_lock_count > 0, "bad value"); + Atomic::dec(&_debug_jni_lock_count); +#endif + } + + // Set the current lock count + static void set_jni_lock_count(int count) { + _jni_lock_count = count; + verify_critical_count(); + } + + // Sets _needs_gc if is_active() is true. Returns is_active(). static bool check_active_before_gc(); // Stalls the caller (who should not be in a jni critical section) @@ -131,22 +148,24 @@ // JNI critical regions are the only participants in this scheme // because they are, by spec, well bounded while in a critical region. // - // Each of the following two method is split into a fast path and a slow - // path. JNICritical_lock is only grabbed in the slow path. + // Each of the following two method is split into a fast path and a + // slow path. JNICritical_lock is only grabbed in the slow path. // _needs_gc is initially false and every java thread will go - // through the fast path (which does the same thing as the slow path - // when _needs_gc is false). When GC happens at a safepoint, - // GC_locker::is_active() is checked. Since there is no safepoint in the - // fast path of lock_critical() and unlock_critical(), there is no race - // condition between the fast path and GC. After _needs_gc is set at a - // safepoint, every thread will go through the slow path after the safepoint. - // Since after a safepoint, each of the following two methods is either - // entered from the method entry and falls into the slow path, or is - // resumed from the safepoints in the method, which only exist in the slow - // path. So when _needs_gc is set, the slow path is always taken, till - // _needs_gc is cleared. + // through the fast path, which simply increments or decrements the + // current thread's critical count. When GC happens at a safepoint, + // GC_locker::is_active() is checked. Since there is no safepoint in + // the fast path of lock_critical() and unlock_critical(), there is + // no race condition between the fast path and GC. After _needs_gc + // is set at a safepoint, every thread will go through the slow path + // after the safepoint. Since after a safepoint, each of the + // following two methods is either entered from the method entry and + // falls into the slow path, or is resumed from the safepoints in + // the method, which only exist in the slow path. So when _needs_gc + // is set, the slow path is always taken, till _needs_gc is cleared. static void lock_critical(JavaThread* thread); static void unlock_critical(JavaThread* thread); + + static address needs_gc_address() { return (address) &_needs_gc; } };
--- a/hotspot/src/share/vm/memory/gcLocker.inline.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/memory/gcLocker.inline.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -28,16 +28,11 @@ #include "memory/gcLocker.hpp" inline bool GC_locker::is_active() { + assert(_needs_gc || SafepointSynchronize::is_at_safepoint(), "only read at safepoint"); + verify_critical_count(); return _lock_count > 0 || _jni_lock_count > 0; } -inline bool GC_locker::check_active_before_gc() { - if (is_active()) { - set_needs_gc(); - } - return is_active(); -} - inline void GC_locker::lock() { // cast away volatile Atomic::inc(&_lock_count); @@ -56,24 +51,28 @@ inline void GC_locker::lock_critical(JavaThread* thread) { if (!thread->in_critical()) { - if (!needs_gc()) { - jni_lock(); - } else { - jni_lock_slow(); + if (needs_gc()) { + // jni_lock call calls enter_critical under the lock so that the + // global lock count and per thread count are in agreement. + jni_lock(thread); + return; } + increment_debug_jni_lock_count(); } thread->enter_critical(); } inline void GC_locker::unlock_critical(JavaThread* thread) { + if (thread->in_last_critical()) { + if (needs_gc()) { + // jni_unlock call calls exit_critical under the lock so that + // the global lock count and per thread count are in agreement. + jni_unlock(thread); + return; + } + decrement_debug_jni_lock_count(); + } thread->exit_critical(); - if (!thread->in_critical()) { - if (!needs_gc()) { - jni_unlock(); - } else { - jni_unlock_slow(); - } - } } #endif // SHARE_VM_MEMORY_GCLOCKER_INLINE_HPP
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -479,11 +479,9 @@ const size_t perm_prev_used = perm_gen()->used(); - if (PrintHeapAtGC) { - Universe::print_heap_before_gc(); - if (Verbose) { - gclog_or_tty->print_cr("GC Cause: %s", GCCause::to_string(gc_cause())); - } + print_heap_before_gc(); + if (Verbose) { + gclog_or_tty->print_cr("GC Cause: %s", GCCause::to_string(gc_cause())); } { @@ -685,9 +683,7 @@ AdaptiveSizePolicy* sp = gen_policy()->size_policy(); AdaptiveSizePolicyOutput(sp, total_collections()); - if (PrintHeapAtGC) { - Universe::print_heap_after_gc(); - } + print_heap_after_gc(); #ifdef TRACESPINNING ParallelTaskTerminator::print_termination_counts();
--- a/hotspot/src/share/vm/memory/genMarkSweep.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -254,7 +254,6 @@ void GenMarkSweep::mark_sweep_phase1(int level, bool clear_all_softrefs) { // Recursively traverse all live objects and mark them - EventMark m("1 mark object"); TraceTime tm("phase 1", PrintGC && Verbose, true, gclog_or_tty); trace(" 1"); @@ -325,7 +324,6 @@ GenCollectedHeap* gch = GenCollectedHeap::heap(); Generation* pg = gch->perm_gen(); - EventMark m("2 compute new addresses"); TraceTime tm("phase 2", PrintGC && Verbose, true, gclog_or_tty); trace("2"); @@ -350,7 +348,6 @@ Generation* pg = gch->perm_gen(); // Adjust the pointers to reflect the new locations - EventMark m("3 adjust pointers"); TraceTime tm("phase 3", PrintGC && Verbose, true, gclog_or_tty); trace("3"); @@ -411,7 +408,6 @@ GenCollectedHeap* gch = GenCollectedHeap::heap(); Generation* pg = gch->perm_gen(); - EventMark m("4 compact heap"); TraceTime tm("phase 4", PrintGC && Verbose, true, gclog_or_tty); trace("4");
--- a/hotspot/src/share/vm/oops/arrayOop.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/oops/arrayOop.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -29,6 +29,7 @@ #ifndef PRODUCT #include "oops/arrayOop.hpp" +#include "oops/oop.inline.hpp" #include "utilities/globalDefinitions.hpp" bool arrayOopDesc::check_max_length_overflow(BasicType type) {
--- a/hotspot/src/share/vm/oops/constantPoolOop.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/oops/constantPoolOop.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -269,7 +269,7 @@ methodOop constantPoolOopDesc::method_at_if_loaded(constantPoolHandle cpool, int which, Bytecodes::Code invoke_code) { assert(!constantPoolCacheOopDesc::is_secondary_index(which), "no indy instruction here"); - if (cpool->cache() == NULL) return false; // nothing to load yet + if (cpool->cache() == NULL) return NULL; // nothing to load yet int cache_index = which - CPCACHE_INDEX_TAG; if (!(cache_index >= 0 && cache_index < cpool->cache()->length())) { if (PrintMiscellaneous && (Verbose||WizardMode)) {
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -570,9 +570,9 @@ void set_method_annotations_of(int idnum, typeArrayOop anno) { set_methods_annotations_of(idnum, anno, &_methods_annotations); } void set_method_parameter_annotations_of(int idnum, typeArrayOop anno) - { set_methods_annotations_of(idnum, anno, &_methods_annotations); } + { set_methods_annotations_of(idnum, anno, &_methods_parameter_annotations); } void set_method_default_annotations_of(int idnum, typeArrayOop anno) - { set_methods_annotations_of(idnum, anno, &_methods_annotations); } + { set_methods_annotations_of(idnum, anno, &_methods_default_annotations); } // allocation DEFINE_ALLOCATE_PERMANENT(instanceKlass);
--- a/hotspot/src/share/vm/oops/klass.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/oops/klass.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -158,9 +158,7 @@ kl->set_next_sibling(NULL); kl->set_alloc_count(0); kl->set_alloc_size(0); -#ifdef TRACE_SET_KLASS_TRACE_ID TRACE_SET_KLASS_TRACE_ID(kl, 0); -#endif kl->set_prototype_header(markOopDesc::prototype()); kl->set_biased_lock_revocation_count(0);
--- a/hotspot/src/share/vm/oops/klass.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/oops/klass.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -265,9 +265,7 @@ markOop _prototype_header; // Used when biased locking is both enabled and disabled for this type jint _biased_lock_revocation_count; -#ifdef TRACE_DEFINE_KLASS_TRACE_ID TRACE_DEFINE_KLASS_TRACE_ID; -#endif public: // returns the enclosing klassOop @@ -688,9 +686,7 @@ jlong last_biased_lock_bulk_revocation_time() { return _last_biased_lock_bulk_revocation_time; } void set_last_biased_lock_bulk_revocation_time(jlong cur_time) { _last_biased_lock_bulk_revocation_time = cur_time; } -#ifdef TRACE_DEFINE_KLASS_METHODS TRACE_DEFINE_KLASS_METHODS; -#endif // garbage collection support virtual void follow_weak_klass_links(
--- a/hotspot/src/share/vm/oops/methodOop.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/oops/methodOop.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -596,6 +596,11 @@ clear_code(); } +address methodOopDesc::critical_native_function() { + methodHandle mh(this); + return NativeLookup::lookup_critical_entry(mh); +} + void methodOopDesc::set_signature_handler(address handler) { address* signature_handler = signature_handler_addr();
--- a/hotspot/src/share/vm/oops/methodOop.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/oops/methodOop.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -403,6 +403,8 @@ native_bind_event_is_interesting = true }; address native_function() const { return *(native_function_addr()); } + address critical_native_function(); + // Must specify a real function (not NULL). // Use clear_native_function() to unregister. void set_native_function(address function, bool post_event_flag);
--- a/hotspot/src/share/vm/opto/loopnode.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/opto/loopnode.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -898,7 +898,7 @@ Node* CountedLoopNode::match_incr_with_optional_truncation( Node* expr, Node** trunc1, Node** trunc2, const TypeInt** trunc_type) { // Quick cutouts: - if (expr == NULL || expr->req() != 3) return false; + if (expr == NULL || expr->req() != 3) return NULL; Node *t1 = NULL; Node *t2 = NULL;
--- a/hotspot/src/share/vm/prims/jvm.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/prims/jvm.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -2716,7 +2716,9 @@ } oop java_thread = JNIHandles::resolve_non_null(jthread); JavaThread* receiver = java_lang_Thread::thread(java_thread); - Events::log("JVM_StopThread thread JavaThread " INTPTR_FORMAT " as oop " INTPTR_FORMAT " [exception " INTPTR_FORMAT "]", receiver, (address)java_thread, throwable); + Events::log_exception(JavaThread::current(), + "JVM_StopThread thread JavaThread " INTPTR_FORMAT " as oop " INTPTR_FORMAT " [exception " INTPTR_FORMAT "]", + receiver, (address)java_thread, throwable); // First check if thread is alive if (receiver != NULL) { // Check if exception is getting thrown at self (use oop equality, since the
--- a/hotspot/src/share/vm/prims/nativeLookup.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/prims/nativeLookup.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -91,6 +91,19 @@ } +char* NativeLookup::critical_jni_name(methodHandle method) { + stringStream st; + // Prefix + st.print("JavaCritical_"); + // Klass name + mangle_name_on(&st, method->klass_name()); + st.print("_"); + // Method name + mangle_name_on(&st, method->name()); + return st.as_string(); +} + + char* NativeLookup::long_jni_name(methodHandle method) { // Signature ignore the wrapping parenteses and the trailing return type stringStream st; @@ -193,6 +206,34 @@ } +address NativeLookup::lookup_critical_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style) { + if (!method->has_native_function()) { + return NULL; + } + + address current_entry = method->native_function(); + + char dll_name[JVM_MAXPATHLEN]; + int offset; + if (os::dll_address_to_library_name(current_entry, dll_name, sizeof(dll_name), &offset)) { + char ebuf[32]; + void* dll = os::dll_load(dll_name, ebuf, sizeof(ebuf)); + if (dll != NULL) { + // Compute complete JNI name for style + stringStream st; + if (os_style) os::print_jni_name_prefix_on(&st, args_size); + st.print_raw(pure_name); + st.print_raw(long_name); + if (os_style) os::print_jni_name_suffix_on(&st, args_size); + char* jni_name = st.as_string(); + return (address)os::dll_lookup(dll, jni_name); + } + } + + return NULL; +} + + // Check all the formats of native implementation name to see if there is one // for the specified method. address NativeLookup::lookup_entry(methodHandle method, bool& in_base_library, TRAPS) { @@ -228,6 +269,58 @@ return entry; // NULL indicates not found } +// Check all the formats of native implementation name to see if there is one +// for the specified method. +address NativeLookup::lookup_critical_entry(methodHandle method) { + if (!CriticalJNINatives) return NULL; + + if (method->is_synchronized() || + !method->is_static()) { + // Only static non-synchronized methods are allowed + return NULL; + } + + ResourceMark rm; + address entry = NULL; + + Symbol* signature = method->signature(); + for (int end = 0; end < signature->utf8_length(); end++) { + if (signature->byte_at(end) == 'L') { + // Don't allow object types + return NULL; + } + } + + // Compute critical name + char* critical_name = critical_jni_name(method); + + // Compute argument size + int args_size = 1 // JNIEnv + + (method->is_static() ? 1 : 0) // class for static methods + + method->size_of_parameters(); // actual parameters + + + // 1) Try JNI short style + entry = lookup_critical_style(method, critical_name, "", args_size, true); + if (entry != NULL) return entry; + + // Compute long name + char* long_name = long_jni_name(method); + + // 2) Try JNI long style + entry = lookup_critical_style(method, critical_name, long_name, args_size, true); + if (entry != NULL) return entry; + + // 3) Try JNI short style without os prefix/suffix + entry = lookup_critical_style(method, critical_name, "", args_size, false); + if (entry != NULL) return entry; + + // 4) Try JNI long style without os prefix/suffix + entry = lookup_critical_style(method, critical_name, long_name, args_size, false); + + return entry; // NULL indicates not found +} + // Check if there are any JVM TI prefixes which have been applied to the native method name. // If any are found, remove them before attemping the look up of the // native implementation again.
--- a/hotspot/src/share/vm/prims/nativeLookup.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/prims/nativeLookup.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -36,15 +36,18 @@ // JNI name computation static char* pure_jni_name(methodHandle method); static char* long_jni_name(methodHandle method); + static char* critical_jni_name(methodHandle method); // Style specific lookup static address lookup_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style, bool& in_base_library, TRAPS); + static address lookup_critical_style(methodHandle method, char* pure_name, const char* long_name, int args_size, bool os_style); static address lookup_base (methodHandle method, bool& in_base_library, TRAPS); static address lookup_entry(methodHandle method, bool& in_base_library, TRAPS); static address lookup_entry_prefixed(methodHandle method, bool& in_base_library, TRAPS); public: // Lookup native function. May throw UnsatisfiedLinkError. static address lookup(methodHandle method, bool& in_base_library, TRAPS); + static address lookup_critical_entry(methodHandle method); // Lookup native functions in base library. static address base_library_lookup(const char* class_name, const char* method_name, const char* signature);
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1400,10 +1400,11 @@ void Arguments::set_parallel_gc_flags() { assert(UseParallelGC || UseParallelOldGC, "Error"); - // If parallel old was requested, automatically enable parallel scavenge. - if (UseParallelOldGC && !UseParallelGC && FLAG_IS_DEFAULT(UseParallelGC)) { - FLAG_SET_DEFAULT(UseParallelGC, true); + // Enable ParallelOld unless it was explicitly disabled (cmd line or rc file). + if (FLAG_IS_DEFAULT(UseParallelOldGC)) { + FLAG_SET_DEFAULT(UseParallelOldGC, true); } + FLAG_SET_DEFAULT(UseParallelGC, true); // If no heap maximum was requested explicitly, use some reasonable fraction // of the physical memory, up to a maximum of 1GB.
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -339,7 +339,6 @@ #ifdef ASSERT assert(cb->is_deoptimization_stub() || cb->is_uncommon_trap_stub(), "just checking"); - Events::log("fetch unroll sp " INTPTR_FORMAT, unpack_sp); #endif #else intptr_t* unpack_sp = stub_frame.sender(&dummy_map).unextended_sp(); @@ -577,6 +576,8 @@ tty->print_cr("DEOPT UNPACKING thread " INTPTR_FORMAT " vframeArray " INTPTR_FORMAT " mode %d", thread, array, exec_mode); } #endif + Events::log(thread, "DEOPT UNPACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT " mode %d", + stub_frame.pc(), stub_frame.sp(), exec_mode); UnrollBlock* info = array->unroll_block(); @@ -981,6 +982,7 @@ #endif // COMPILER2 vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk) { + Events::log(thread, "DEOPT PACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, fr.pc(), fr.sp()); #ifndef PRODUCT if (TraceDeoptimization) { @@ -1026,7 +1028,6 @@ // Compare the vframeArray to the collected vframes assert(array->structural_compare(thread, chunk), "just checking"); - Events::log("# vframes = %d", (intptr_t)chunk->length()); #ifndef PRODUCT if (TraceDeoptimization) { @@ -1124,8 +1125,6 @@ gather_statistics(Reason_constraint, Action_none, Bytecodes::_illegal); - EventMark m("Deoptimization (pc=" INTPTR_FORMAT ", sp=" INTPTR_FORMAT ")", fr.pc(), fr.id()); - // Patch the nmethod so that when execution returns to it we will // deopt the execution state and return to the interpreter. fr.deoptimize(thread); @@ -1239,6 +1238,10 @@ // before we are done with it. nmethodLocker nl(fr.pc()); + // Log a message + Events::log_deopt_message(thread, "Uncommon trap %d fr.pc " INTPTR_FORMAT, + trap_request, fr.pc()); + { ResourceMark rm; @@ -1249,7 +1252,6 @@ DeoptAction action = trap_request_action(trap_request); jint unloaded_class_index = trap_request_index(trap_request); // CP idx or -1 - Events::log("Uncommon trap occurred @" INTPTR_FORMAT " unloaded_class_index = %d", fr.pc(), (int) trap_request); vframe* vf = vframe::new_vframe(&fr, ®_map, thread); compiledVFrame* cvf = compiledVFrame::cast(vf);
--- a/hotspot/src/share/vm/runtime/frame.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/runtime/frame.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -570,7 +570,7 @@ InterpreterCodelet* desc = Interpreter::codelet_containing(pc()); if (desc != NULL) { st->print("~"); - desc->print(); + desc->print_on(st); NOT_PRODUCT(begin = desc->code_begin(); end = desc->code_end();) } else { st->print("~interpreter");
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -26,6 +26,17 @@ #define SHARE_VM_RUNTIME_GLOBALS_HPP #include "utilities/debug.hpp" + +// use this for flags that are true per default in the tiered build +// but false in non-tiered builds, and vice versa +#ifdef TIERED +#define trueInTiered true +#define falseInTiered false +#else +#define trueInTiered false +#define falseInTiered true +#endif + #ifdef TARGET_ARCH_x86 # include "globals_x86.hpp" #endif @@ -353,16 +364,6 @@ #define falseInProduct true #endif -// use this for flags that are true per default in the tiered build -// but false in non-tiered builds, and vice versa -#ifdef TIERED -#define trueInTiered true -#define falseInTiered false -#else -#define trueInTiered false -#define falseInTiered true -#endif - #ifdef JAVASE_EMBEDDED #define falseInEmbedded false #else @@ -658,6 +659,12 @@ develop(bool, SpecialArraysEquals, true, \ "special version of Arrays.equals(char[],char[])") \ \ + product(bool, CriticalJNINatives, true, \ + "check for critical JNI entry points") \ + \ + notproduct(bool, StressCriticalJNINatives, false, \ + "Exercise register saving code in critical natives") \ + \ product(bool, UseSSE42Intrinsics, false, \ "SSE4.2 versions of intrinsics") \ \ @@ -735,8 +742,11 @@ product(bool, MaxFDLimit, true, \ "Bump the number of file descriptors to max in solaris.") \ \ - notproduct(bool, LogEvents, trueInDebug, \ - "Enable Event log") \ + diagnostic(bool, LogEvents, true, \ + "Enable the various ring buffer event logs") \ + \ + diagnostic(intx, LogEventsBufferEntries, 10, \ + "Enable the various ring buffer event logs") \ \ product(bool, BytecodeVerificationRemote, true, \ "Enables the Java bytecode verifier for remote classes") \ @@ -1042,6 +1052,9 @@ notproduct(bool, PrintSystemDictionaryAtExit, false, \ "Prints the system dictionary at exit") \ \ + experimental(intx, PredictedLoadedClassCount, 0, \ + "Experimental: Tune loaded class cache starting size.") \ + \ diagnostic(bool, UnsyncloadClass, false, \ "Unstable: VM calls loadClass unsynchronized. Custom " \ "class loader must call VM synchronized for findClass " \
--- a/hotspot/src/share/vm/runtime/init.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/runtime/init.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -65,7 +65,7 @@ void InlineCacheBuffer_init(); void compilerOracle_init(); void compilationPolicy_init(); - +void compileBroker_init(); // Initialization after compiler initialization bool universe_post_init(); // must happen after compiler_init @@ -120,6 +120,7 @@ InlineCacheBuffer_init(); compilerOracle_init(); compilationPolicy_init(); + compileBroker_init(); VMRegImpl::set_regName(); if (!universe_post_init()) {
--- a/hotspot/src/share/vm/runtime/mutex.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/runtime/mutex.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -1296,10 +1296,6 @@ assert(this->rank() >= 0, "bad lock rank"); - if (LogMultipleMutexLocking && locks != NULL) { - Events::log("thread " INTPTR_FORMAT " locks %s, already owns %s", new_owner, name(), locks->name()); - } - // Deadlock avoidance rules require us to acquire Mutexes only in // a global total order. For example m1 is the lowest ranked mutex // that the thread holds and m2 is the mutex the thread is trying @@ -1343,10 +1339,6 @@ #ifdef ASSERT Monitor *locks = old_owner->owned_locks(); - if (LogMultipleMutexLocking && locks != this) { - Events::log("thread " INTPTR_FORMAT " unlocks %s, still owns %s", old_owner, this->name(), locks->name()); - } - // remove "this" from the owned locks list Monitor *prev = NULL;
--- a/hotspot/src/share/vm/runtime/safepoint.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/runtime/safepoint.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -95,6 +95,7 @@ SafepointSynchronize::SynchronizeState volatile SafepointSynchronize::_state = SafepointSynchronize::_not_synchronized; volatile int SafepointSynchronize::_waiting_to_block = 0; volatile int SafepointSynchronize::_safepoint_counter = 0; +int SafepointSynchronize::_current_jni_active_count = 0; long SafepointSynchronize::_end_of_last_safepoint = 0; static volatile int PageArmed = 0 ; // safepoint polling page is RO|RW vs PROT_NONE static volatile int TryingToBlock = 0 ; // proximate value -- for advisory use only @@ -135,9 +136,11 @@ RuntimeService::record_safepoint_begin(); - { MutexLocker mu(Safepoint_lock); + // Reset the count of active JNI critical threads + _current_jni_active_count = 0; + // Set number of threads to wait for, before we initiate the callbacks _waiting_to_block = nof_threads; TryingToBlock = 0 ; @@ -375,6 +378,9 @@ OrderAccess::fence(); + // Update the count of active JNI critical regions + GC_locker::set_jni_lock_count(_current_jni_active_count); + if (TraceSafepoint) { VM_Operation *op = VMThread::vm_operation(); tty->print_cr("Entering safepoint region: %s", (op != NULL) ? op->name() : "no vm operation"); @@ -392,7 +398,6 @@ // Record how much time spend on the above cleanup tasks update_statistics_on_cleanup_end(os::javaTimeNanos()); } - } } // Wake up all threads, so they are ready to resume execution after the safepoint @@ -539,6 +544,42 @@ } +// See if the thread is running inside a lazy critical native and +// update the thread critical count if so. Also set a suspend flag to +// cause the native wrapper to return into the JVM to do the unlock +// once the native finishes. +void SafepointSynchronize::check_for_lazy_critical_native(JavaThread *thread, JavaThreadState state) { + if (state == _thread_in_native && + thread->has_last_Java_frame() && + thread->frame_anchor()->walkable()) { + // This thread might be in a critical native nmethod so look at + // the top of the stack and increment the critical count if it + // is. + frame wrapper_frame = thread->last_frame(); + CodeBlob* stub_cb = wrapper_frame.cb(); + if (stub_cb != NULL && + stub_cb->is_nmethod() && + stub_cb->as_nmethod_or_null()->is_lazy_critical_native()) { + // A thread could potentially be in a critical native across + // more than one safepoint, so only update the critical state on + // the first one. When it returns it will perform the unlock. + if (!thread->do_critical_native_unlock()) { +#ifdef ASSERT + if (!thread->in_critical()) { + GC_locker::increment_debug_jni_lock_count(); + } +#endif + thread->enter_critical(); + // Make sure the native wrapper calls back on return to + // perform the needed critical unlock. + thread->set_critical_native_unlock(); + } + } + } +} + + + // ------------------------------------------------------------------------------------------------------- // Implementation of Safepoint callback point @@ -585,6 +626,11 @@ _waiting_to_block--; thread->safepoint_state()->set_has_called_back(true); + if (thread->in_critical()) { + // Notice that this thread is in a critical section + increment_jni_active_count(); + } + // Consider (_waiting_to_block < 2) to pipeline the wakeup of the VM thread if (_waiting_to_block == 0) { Safepoint_lock->notify_all(); @@ -861,8 +907,13 @@ // running, but are actually at a safepoint. We will happily // agree and update the safepoint state here. if (SafepointSynchronize::safepoint_safe(_thread, state)) { - roll_forward(_at_safepoint); - return; + roll_forward(_at_safepoint); + SafepointSynchronize::check_for_lazy_critical_native(_thread, state); + if (_thread->in_critical()) { + // Notice that this thread is in a critical section + SafepointSynchronize::increment_jni_active_count(); + } + return; } if (state == _thread_in_vm) {
--- a/hotspot/src/share/vm/runtime/safepoint.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/runtime/safepoint.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -29,6 +29,7 @@ #include "code/nmethod.hpp" #include "memory/allocation.hpp" #include "runtime/extendedPC.hpp" +#include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" #include "utilities/ostream.hpp" @@ -92,6 +93,7 @@ private: static volatile SynchronizeState _state; // Threads might read this flag directly, without acquireing the Threads_lock static volatile int _waiting_to_block; // number of threads we are waiting for to block + static int _current_jni_active_count; // Counts the number of active critical natives during the safepoint // This counter is used for fast versions of jni_Get<Primitive>Field. // An even value means there is no ongoing safepoint operations. @@ -138,6 +140,8 @@ static bool safepoint_safe(JavaThread *thread, JavaThreadState state); + static void check_for_lazy_critical_native(JavaThread *thread, JavaThreadState state); + // Query inline static bool is_at_safepoint() { return _state == _synchronized; } inline static bool is_synchronizing() { return _state == _synchronizing; } @@ -146,6 +150,11 @@ return (_state != _not_synchronized); } + inline static void increment_jni_active_count() { + assert_locked_or_safepoint(Safepoint_lock); + _current_jni_active_count++; + } + // Called when a thread volantary blocks static void block(JavaThread *thread); static void signal_thread_at_safepoint() { _waiting_to_block--; }
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -886,9 +886,9 @@ // for AbortVMOnException flag NOT_PRODUCT(Exceptions::debug_check_abort("java.lang.NullPointerException")); if (exception_kind == IMPLICIT_NULL) { - Events::log("Implicit null exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc); + Events::log_exception(thread, "Implicit null exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc); } else { - Events::log("Implicit division by zero exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc); + Events::log_exception(thread, "Implicit division by zero exception at " INTPTR_FORMAT " to " INTPTR_FORMAT, pc, target_pc); } return target_pc; } @@ -1541,7 +1541,6 @@ if (caller.is_compiled_frame() && !caller.is_deoptimized_frame()) { address pc = caller.pc(); - Events::log("update call-site at pc " INTPTR_FORMAT, pc); // Default call_addr is the location of the "basic" call. // Determine the address of the call we a reresolving. With @@ -2679,6 +2678,20 @@ return nm; } +JRT_ENTRY_NO_ASYNC(void, SharedRuntime::block_for_jni_critical(JavaThread* thread)) + assert(thread == JavaThread::current(), "must be"); + // The code is about to enter a JNI lazy critical native method and + // _needs_gc is true, so if this thread is already in a critical + // section then just return, otherwise this thread should block + // until needs_gc has been cleared. + if (thread->in_critical()) { + return; + } + // Lock and unlock a critical section to give the system a chance to block + GC_locker::lock_critical(thread); + GC_locker::unlock_critical(thread); +JRT_END + #ifdef HAVE_DTRACE_H // Create a dtrace nmethod for this method. The wrapper converts the // java compiled calling convention to the native convention, makes a dummy call
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -462,6 +462,9 @@ VMRegPair *regs, BasicType ret_type ); + // Block before entering a JNI critical method + static void block_for_jni_critical(JavaThread* thread); + #ifdef HAVE_DTRACE_H // Generate a dtrace wrapper for a given method. The method takes arguments // in the Java compiled code convention, marshals them to the native
--- a/hotspot/src/share/vm/runtime/thread.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/runtime/thread.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -33,6 +33,7 @@ #include "interpreter/linkResolver.hpp" #include "interpreter/oopMapCache.hpp" #include "jvmtifiles/jvmtiEnv.hpp" +#include "memory/gcLocker.inline.hpp" #include "memory/oopFactory.hpp" #include "memory/universe.inline.hpp" #include "oops/instanceKlass.hpp" @@ -1600,8 +1601,6 @@ // java.lang.Thread.dispatchUncaughtException if (uncaught_exception.not_null()) { Handle group(this, java_lang_Thread::threadGroup(threadObj())); - Events::log("uncaught exception INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT", - (address)uncaught_exception(), (address)threadObj(), (address)group()); { EXCEPTION_MARK; // Check if the method Thread.dispatchUncaughtException() exists. If so @@ -2280,6 +2279,26 @@ } } +// This is a variant of the normal +// check_special_condition_for_native_trans with slightly different +// semantics for use by critical native wrappers. It does all the +// normal checks but also performs the transition back into +// thread_in_Java state. This is required so that critical natives +// can potentially block and perform a GC if they are the last thread +// exiting the GC_locker. +void JavaThread::check_special_condition_for_native_trans_and_transition(JavaThread *thread) { + check_special_condition_for_native_trans(thread); + + // Finish the transition + thread->set_thread_state(_thread_in_Java); + + if (thread->do_critical_native_unlock()) { + ThreadInVMfromJavaNoAsyncException tiv(thread); + GC_locker::unlock_critical(thread); + thread->clear_critical_native_unlock(); + } +} + // We need to guarantee the Threads_lock here, since resumes are not // allowed during safepoint synchronization // Can only resume from an external suspension @@ -3885,7 +3904,7 @@ ThreadService::add_thread(p, daemon); // Possible GC point. - Events::log("Thread added: " INTPTR_FORMAT, p); + Events::log(p, "Thread added: " INTPTR_FORMAT, p); } void Threads::remove(JavaThread* p) { @@ -3930,7 +3949,7 @@ } // unlock Threads_lock // Since Events::log uses a lock, we grab it outside the Threads_lock - Events::log("Thread exited: " INTPTR_FORMAT, p); + Events::log(p, "Thread exited: " INTPTR_FORMAT, p); } // Threads_lock must be held when this is called (or must be called during a safepoint)
--- a/hotspot/src/share/vm/runtime/thread.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/runtime/thread.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -182,7 +182,8 @@ _ext_suspended = 0x40000000U, // thread has self-suspended _deopt_suspend = 0x10000000U, // thread needs to self suspend for deopt - _has_async_exception = 0x00000001U // there is a pending async exception + _has_async_exception = 0x00000001U, // there is a pending async exception + _critical_native_unlock = 0x00000002U // Must call back to unlock JNI critical lock }; // various suspension related flags - atomically updated @@ -350,6 +351,15 @@ clear_suspend_flag(_has_async_exception); } + bool do_critical_native_unlock() const { return (_suspend_flags & _critical_native_unlock) != 0; } + + void set_critical_native_unlock() { + set_suspend_flag(_critical_native_unlock); + } + void clear_critical_native_unlock() { + clear_suspend_flag(_critical_native_unlock); + } + // Support for Unhandled Oop detection #ifdef CHECK_UNHANDLED_OOPS private: @@ -1038,6 +1048,11 @@ // Check for async exception in addition to safepoint and suspend request. static void check_special_condition_for_native_trans(JavaThread *thread); + // Same as check_special_condition_for_native_trans but finishes the + // transition into thread_in_Java mode so that it can potentially + // block. + static void check_special_condition_for_native_trans_and_transition(JavaThread *thread); + bool is_ext_suspend_completed(bool called_by_wait, int delay, uint32_t *bits); bool is_ext_suspend_completed_with_lock(uint32_t *bits) { MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag); @@ -1310,8 +1325,10 @@ // JNI critical regions. These can nest. bool in_critical() { return _jni_active_critical > 0; } - void enter_critical() { assert(Thread::current() == this, - "this must be current thread"); + bool in_last_critical() { return _jni_active_critical == 1; } + void enter_critical() { assert(Thread::current() == this || + Thread::current()->is_VM_thread() && SafepointSynchronize::is_synchronizing(), + "this must be current thread or synchronizing"); _jni_active_critical++; } void exit_critical() { assert(Thread::current() == this, "this must be current thread");
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 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 @@ -2261,13 +2261,6 @@ \ declare_constant(SymbolTable::symbol_table_size) \ \ - /********************/ \ - /* SystemDictionary */ \ - /********************/ \ - \ - declare_constant(SystemDictionary::_loader_constraint_size) \ - declare_constant(SystemDictionary::_nof_buckets) \ - \ /***********************************/ \ /* LoaderConstraintTable constants */ \ /***********************************/ \
--- a/hotspot/src/share/vm/trace/traceMacros.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/trace/traceMacros.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -40,4 +40,8 @@ #define TRACE_START() true #define TRACE_INITIALIZE() 0 +#define TRACE_SET_KLASS_TRACE_ID(x1, x2) do { } while (0) +#define TRACE_DEFINE_KLASS_METHODS typedef int ___IGNORED_hs_trace_type1 +#define TRACE_DEFINE_KLASS_TRACE_ID typedef int ___IGNORED_hs_trace_type2 + #endif
--- a/hotspot/src/share/vm/utilities/debug.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/utilities/debug.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -601,18 +601,6 @@ } -extern "C" void events() { - Command c("events"); - Events::print_last(tty, 50); -} - - -extern "C" void nevents(int n) { - Command c("events"); - Events::print_last(tty, n); -} - - // Given a heap address that was valid before the most recent GC, if // the oop that used to contain it is still live, prints the new // location of the oop and the address. Useful for tracking down
--- a/hotspot/src/share/vm/utilities/debug.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/utilities/debug.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -33,16 +33,23 @@ // Simple class to format the ctor arguments into a fixed-sized buffer. template <size_t bufsz = 256> class FormatBuffer { -public: + public: inline FormatBuffer(const char * format, ...); inline void append(const char* format, ...); + inline void print(const char* format, ...); + inline void printv(const char* format, va_list ap); operator const char *() const { return _buf; } -private: + char* buffer() { return _buf; } + int size() { return bufsz; } + + private: FormatBuffer(const FormatBuffer &); // prevent copies -private: + protected: char _buf[bufsz]; + + inline FormatBuffer(); }; template <size_t bufsz> @@ -54,6 +61,24 @@ } template <size_t bufsz> +FormatBuffer<bufsz>::FormatBuffer() { + _buf[0] = '\0'; +} + +template <size_t bufsz> +void FormatBuffer<bufsz>::print(const char * format, ...) { + va_list argp; + va_start(argp, format); + jio_vsnprintf(_buf, bufsz, format, argp); + va_end(argp); +} + +template <size_t bufsz> +void FormatBuffer<bufsz>::printv(const char * format, va_list argp) { + jio_vsnprintf(_buf, bufsz, format, argp); +} + +template <size_t bufsz> void FormatBuffer<bufsz>::append(const char* format, ...) { // Given that the constructor does a vsnprintf we can assume that // _buf is already initialized.
--- a/hotspot/src/share/vm/utilities/events.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/utilities/events.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -26,6 +26,7 @@ #include "memory/allocation.inline.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/osThread.hpp" +#include "runtime/threadCritical.hpp" #include "runtime/threadLocalStorage.hpp" #include "runtime/timer.hpp" #include "utilities/events.hpp" @@ -43,184 +44,40 @@ #endif -#ifndef PRODUCT +EventLog* Events::_logs = NULL; +StringEventLog* Events::_messages = NULL; +StringEventLog* Events::_exceptions = NULL; +StringEventLog* Events::_deopt_messages = NULL; -//////////////////////////////////////////////////////////////////////////// -// Event +EventLog::EventLog() { + // This normally done during bootstrap when we're only single + // threaded but use a ThreadCritical to ensure inclusion in case + // some are created slightly late. + ThreadCritical tc; + _next = Events::_logs; + Events::_logs = this; +} -typedef u4 EventID; - -class Event VALUE_OBJ_CLASS_SPEC { - private: - jlong _time_tick; - intx _thread_id; - const char* _format; - int _indent; - intptr_t _arg_1; - intptr_t _arg_2; - intptr_t _arg_3; - - // only EventBuffer::add_event() can assign event id - friend class EventBuffer; - EventID _id; - - public: - - void clear() { _format = NULL; } - - EventID id() const { return _id; } - - void fill(int indent, const char* format, intptr_t arg_1, intptr_t arg_2, intptr_t arg_3) { - _format = format; - _arg_1 = arg_1; - _arg_2 = arg_2; - _arg_3 = arg_3; - - _indent = indent; - - _thread_id = os::current_thread_id(); - _time_tick = os::elapsed_counter(); - } - - void print_on(outputStream *st) { - if (_format == NULL) return; - st->print(" %d", _thread_id); - st->print(" %3.2g ", (double)_time_tick / os::elapsed_frequency()); - st->fill_to(20); - for (int index = 0; index < _indent; index++) { - st->print("| "); - } - st->print_cr(_format, _arg_1, _arg_2, _arg_3); - } -}; - -//////////////////////////////////////////////////////////////////////////// -// EventBuffer -// -// Simple lock-free event queue. Every event has a unique 32-bit id. -// It's fine if two threads add events at the same time, because they -// will get different event id, and then write to different buffer location. -// However, it is assumed that add_event() is quick enough (or buffer size -// is big enough), so when one thread is adding event, there can't be more -// than "size" events created by other threads; otherwise we'll end up having -// two threads writing to the same location. - -class EventBuffer : AllStatic { - private: - static Event* buffer; - static int size; - static jint indent; - static volatile EventID _current_event_id; - - static EventID get_next_event_id() { - return (EventID)Atomic::add(1, (jint*)&_current_event_id); - } - - public: - static void inc_indent() { Atomic::inc(&indent); } - static void dec_indent() { Atomic::dec(&indent); } - - static bool get_event(EventID id, Event* event) { - int index = (int)(id % size); - if (buffer[index].id() == id) { - memcpy(event, &buffer[index], sizeof(Event)); - // check id again; if buffer[index] is being updated by another thread, - // event->id() will contain different value. - return (event->id() == id); - } else { - // id does not match - id is invalid, or event is overwritten - return false; - } - } - - // add a new event to the queue; if EventBuffer is full, this call will - // overwrite the oldest event in the queue - static EventID add_event(const char* format, - intptr_t arg_1, intptr_t arg_2, intptr_t arg_3) { - // assign a unique id - EventID id = get_next_event_id(); - - // event will be copied to buffer[index] - int index = (int)(id % size); - - // first, invalidate id, buffer[index] can't have event with id = index + 2 - buffer[index]._id = index + 2; - - // make sure everyone has seen that buffer[index] is invalid - OrderAccess::fence(); - - // ... before updating its value - buffer[index].fill(indent, format, arg_1, arg_2, arg_3); - - // finally, set up real event id, now buffer[index] contains valid event - OrderAccess::release_store(&(buffer[index]._id), id); - - return id; - } - - static void print_last(outputStream *st, int number) { - st->print_cr("[Last %d events in the event buffer]", number); - st->print_cr("-<thd>-<elapsed sec>-<description>---------------------"); - - int count = 0; - EventID id = _current_event_id; - while (count < number) { - Event event; - if (get_event(id, &event)) { - event.print_on(st); - } - id--; - count++; - } - } - - static void print_all(outputStream* st) { - print_last(st, size); - } - - static void init() { - // Allocate the event buffer - size = EventLogLength; - buffer = NEW_C_HEAP_ARRAY(Event, size); - - _current_event_id = 0; - - // Clear the event buffer - for (int index = 0; index < size; index++) { - buffer[index]._id = index + 1; // index + 1 is invalid id - buffer[index].clear(); - } - } -}; - -Event* EventBuffer::buffer; -int EventBuffer::size; -volatile EventID EventBuffer::_current_event_id; -int EventBuffer::indent; - -//////////////////////////////////////////////////////////////////////////// -// Events - -// Events::log() is safe for signal handlers -void Events::log(const char* format, ...) { - if (LogEvents) { - va_list ap; - va_start(ap, format); - intptr_t arg_1 = va_arg(ap, intptr_t); - intptr_t arg_2 = va_arg(ap, intptr_t); - intptr_t arg_3 = va_arg(ap, intptr_t); - va_end(ap); - - EventBuffer::add_event(format, arg_1, arg_2, arg_3); +// For each registered event logger, print out the current contents of +// the buffer. This is normally called when the JVM is crashing. +void Events::print_all(outputStream* out) { + EventLog* log = _logs; + while (log != NULL) { + log->print_log_on(out); + log = log->next(); } } -void Events::print_all(outputStream *st) { - EventBuffer::print_all(st); +void Events::init() { + if (LogEvents) { + _messages = new StringEventLog("Events"); + _exceptions = new StringEventLog("Internal exceptions"); + _deopt_messages = new StringEventLog("Deoptimization events"); + } } -void Events::print_last(outputStream *st, int number) { - EventBuffer::print_last(st, number); +void eventlog_init() { + Events::init(); } /////////////////////////////////////////////////////////////////////////// @@ -230,37 +87,17 @@ if (LogEvents) { va_list ap; va_start(ap, format); - intptr_t arg_1 = va_arg(ap, intptr_t); - intptr_t arg_2 = va_arg(ap, intptr_t); - intptr_t arg_3 = va_arg(ap, intptr_t); + // Save a copy of begin message and log it. + _buffer.printv(format, ap); + Events::log(NULL, _buffer); va_end(ap); - - EventBuffer::add_event(format, arg_1, arg_2, arg_3); - EventBuffer::inc_indent(); } } EventMark::~EventMark() { if (LogEvents) { - EventBuffer::dec_indent(); - EventBuffer::add_event("done", 0, 0, 0); + // Append " done" to the begin message and log it + _buffer.append(" done"); + Events::log(NULL, _buffer); } } - -/////////////////////////////////////////////////////////////////////////// - -void eventlog_init() { - EventBuffer::init(); -} - -int print_all_events(outputStream *st) { - EventBuffer::print_all(st); - return 1; -} - -#else - -void eventlog_init() {} -int print_all_events(outputStream *st) { return 0; } - -#endif // PRODUCT
--- a/hotspot/src/share/vm/utilities/events.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/utilities/events.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -26,7 +26,10 @@ #define SHARE_VM_UTILITIES_EVENTS_HPP #include "memory/allocation.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/thread.hpp" #include "utilities/top.hpp" +#include "utilities/vmError.hpp" // Events and EventMark provide interfaces to log events taking place in the vm. // This facility is extremly useful for post-mortem debugging. The eventlog @@ -47,26 +50,246 @@ // Max 3 arguments are saved for each logged event. // -class Events : AllStatic { +// The base event log dumping class that is registered for dumping at +// crash time. This is a very generic interface that is mainly here +// for completeness. Normally the templated EventLogBase would be +// subclassed to provide different log types. +class EventLog : public CHeapObj { + friend class Events; + + private: + EventLog* _next; + + EventLog* next() const { return _next; } + public: - // Logs an event, format as printf - static void log(const char* format, ...) PRODUCT_RETURN; + // Automatically registers the log so that it will be printed during + // crashes. + EventLog(); - // Prints all events in the buffer - static void print_all(outputStream* st) PRODUCT_RETURN; - - // Prints last number events from the event buffer - static void print_last(outputStream *st, int number) PRODUCT_RETURN; + virtual void print_log_on(outputStream* out) = 0; }; + +// A templated subclass of EventLog that provides basic ring buffer +// functionality. Most event loggers should subclass this, possibly +// providing a more featureful log function if the existing copy +// semantics aren't appropriate. The name is used as the label of the +// log when it is dumped during a crash. +template <class T> class EventLogBase : public EventLog { + template <class X> class EventRecord { + public: + jlong timestamp; + Thread* thread; + X data; + }; + + protected: + Mutex _mutex; + const char* _name; + int _length; + int _index; + int _count; + EventRecord<T>* _records; + + public: + EventLogBase<T>(const char* name, int length = LogEventsBufferEntries): + _name(name), + _length(length), + _count(0), + _index(0), + _mutex(Mutex::event, name) { + _records = new EventRecord<T>[length]; + } + + // move the ring buffer to next open slot and return the index of + // the slot to use for the current message. Should only be called + // while mutex is held. + int compute_log_index() { + int index = _index; + if (_count < _length) _count++; + _index++; + if (_index >= _length) _index = 0; + return index; + } + + bool should_log() { + // Don't bother adding new entries when we're crashing. This also + // avoids mutating the ring buffer when printing the log. + return !VMError::fatal_error_in_progress(); + } + + // Print the contents of the log + void print_log_on(outputStream* out); + + private: + void print_log_impl(outputStream* out); + + // Print a single element. A templated implementation might need to + // be declared by subclasses. + void print(outputStream* out, T& e); + + void print(outputStream* out, EventRecord<T>& e) { + out->print("Event: " INT64_FORMAT " ", e.timestamp); + if (e.thread != NULL) { + out->print("Thread " INTPTR_FORMAT " ", e.thread); + } + print(out, e.data); + } +}; + +// A simple wrapper class for fixed size text messages. +class StringLogMessage : public FormatBuffer<132> { + public: + // Wrap this buffer in a stringStream. + stringStream stream() { + return stringStream(_buf, sizeof(_buf)); + } +}; + +// A simple ring buffer of fixed size text messages. +class StringEventLog : public EventLogBase<StringLogMessage> { + public: + StringEventLog(const char* name, int count = LogEventsBufferEntries) : EventLogBase<StringLogMessage>(name, count) {} + + void logv(Thread* thread, const char* format, va_list ap) { + if (!should_log()) return; + + jlong timestamp = os::javaTimeNanos() / NANOSECS_PER_MILLISEC; + MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag); + int index = compute_log_index(); + _records[index].thread = thread; + _records[index].timestamp = timestamp; + _records[index].data.printv(format, ap); + } + + void log(Thread* thread, const char* format, ...) { + va_list ap; + va_start(ap, format); + logv(thread, format, ap); + va_end(ap); + } + +}; + + + +class Events : AllStatic { + friend class EventLog; + + private: + static EventLog* _logs; + + // A log for generic messages that aren't well categorized. + static StringEventLog* _messages; + + // A log for internal exception related messages, like internal + // throws and implicit exceptions. + static StringEventLog* _exceptions; + + // Deoptization related messages + static StringEventLog* _deopt_messages; + + public: + static void print_all(outputStream* out); + + static void print() { + print_all(tty); + } + + // Logs a generic message with timestamp and format as printf. + static void log(Thread* thread, const char* format, ...); + + // Log exception related message + static void log_exception(Thread* thread, const char* format, ...); + + static void log_deopt_message(Thread* thread, const char* format, ...); + + // Register default loggers + static void init(); +}; + + +inline void Events::log(Thread* thread, const char* format, ...) { + if (LogEvents) { + va_list ap; + va_start(ap, format); + _messages->logv(thread, format, ap); + va_end(ap); + } +} + +inline void Events::log_exception(Thread* thread, const char* format, ...) { + if (LogEvents) { + va_list ap; + va_start(ap, format); + _exceptions->logv(thread, format, ap); + va_end(ap); + } +} + +inline void Events::log_deopt_message(Thread* thread, const char* format, ...) { + if (LogEvents) { + va_list ap; + va_start(ap, format); + _deopt_messages->logv(thread, format, ap); + va_end(ap); + } +} + + +template <class T> +inline void EventLogBase<T>::print_log_on(outputStream* out) { + if (ThreadLocalStorage::get_thread_slow() == NULL) { + // Not a regular Java thread so don't bother locking + print_log_impl(out); + } else { + MutexLockerEx ml(&_mutex, Mutex::_no_safepoint_check_flag); + print_log_impl(out); + } +} + +// Dump the ring buffer entries that current have entries. +template <class T> +inline void EventLogBase<T>::print_log_impl(outputStream* out) { + out->print_cr("%s (%d events):", _name, _count); + if (_count == 0) { + out->print_cr("No events"); + return; + } + + if (_count < _length) { + for (int i = 0; i < _count; i++) { + print(out, _records[i]); + } + } else { + for (int i = _index; i < _length; i++) { + print(out, _records[i]); + } + for (int i = 0; i < _index; i++) { + print(out, _records[i]); + } + } + out->cr(); +} + +// Implement a printing routine for the StringLogMessage +template <> +inline void EventLogBase<StringLogMessage>::print(outputStream* out, StringLogMessage& lm) { + out->print_raw(lm); + out->cr(); +} + +// Place markers for the beginning and end up of a set of events. +// These end up in the default log. class EventMark : public StackObj { + StringLogMessage _buffer; + public: // log a begin event, format as printf - EventMark(const char* format, ...) PRODUCT_RETURN; + EventMark(const char* format, ...); // log an end event - ~EventMark() PRODUCT_RETURN; + ~EventMark(); }; -int print_all_events(outputStream *st); - #endif // SHARE_VM_UTILITIES_EVENTS_HPP
--- a/hotspot/src/share/vm/utilities/exceptions.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/utilities/exceptions.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -160,7 +160,7 @@ thread->set_pending_exception(h_exception(), file, line); // vm log - Events::log("throw_exception " INTPTR_FORMAT, (address)h_exception()); + Events::log_exception(thread, "Threw " INTPTR_FORMAT " at %s:%d", (address)h_exception(), file, line); }
--- a/hotspot/src/share/vm/utilities/hashtable.hpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/utilities/hashtable.hpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -183,7 +183,6 @@ // Accessor int entry_size() const { return _entry_size; } - int table_size() { return _table_size; } // The following method is MT-safe and may be used with caution. BasicHashtableEntry* bucket(int i); @@ -195,6 +194,7 @@ BasicHashtableEntry* new_entry(unsigned int hashValue); public: + int table_size() { return _table_size; } void set_entry(int index, BasicHashtableEntry* entry); void add_entry(int index, BasicHashtableEntry* entry);
--- a/hotspot/src/share/vm/utilities/vmError.cpp Thu Feb 02 09:39:33 2012 -0800 +++ b/hotspot/src/share/vm/utilities/vmError.cpp Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -36,6 +36,7 @@ #include "utilities/decoder.hpp" #include "utilities/defaultStream.hpp" #include "utilities/errorReporter.hpp" +#include "utilities/events.hpp" #include "utilities/top.hpp" #include "utilities/vmError.hpp" @@ -693,7 +694,14 @@ st->cr(); } - STEP(200, "(printing dynamic libraries)" ) + STEP(200, "(printing ring buffers)" ) + + if (_verbose) { + Events::print_all(st); + st->cr(); + } + + STEP(205, "(printing dynamic libraries)" ) if (_verbose) { // dynamic libraries, or memory map
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/7090976/Test7090976.java Wed Jul 05 18:01:59 2017 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 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. + * + */ + +/** + * @test + * @bug 7090976 + * @summary Eclipse/CDT causes a JVM crash while indexing C++ code + * + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement Test7090976 + */ + +public class Test7090976 { + + static interface I1 { + public void m1(); + }; + + static interface I2 { + public void m2(); + }; + + static interface I extends I1,I2 { + } + + static class A implements I1 { + int v = 0; + int v2; + + public void m1() { + v2 = v; + } + } + + static class B implements I2 { + Object v = new Object(); + Object v2; + + public void m2() { + v2 = v; + } + } + + private void test(A a) + { + if (a instanceof I) { + I i = (I)a; + i.m1(); + i.m2(); + } + } + + public static void main(String[] args) + { + Test7090976 t = new Test7090976(); + A a = new A(); + B b = new B(); + for (int i = 0; i < 10000; i++) { + t.test(a); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/7141637/SpreadNullArg.java Wed Jul 05 18:01:59 2017 +0200 @@ -0,0 +1,62 @@ +/* + * Copyright 2011 SAP AG. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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 SpreadNullArg + * @bug 7141637 + * @summary verifies that the MethodHandle spread adapter can gracefully handle null arguments. + * @run main SpreadNullArg + * @author volker.simonis@gmail.com + */ + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +public class SpreadNullArg { + + public static void main(String args[]) { + + MethodType mt_ref_arg = MethodType.methodType(int.class, Integer.class); + MethodHandle mh_spreadInvoker = MethodHandles.spreadInvoker(mt_ref_arg, 0); + MethodHandle mh_spread_target; + int result = 42; + + try { + mh_spread_target = + MethodHandles.lookup().findStatic(SpreadNullArg.class, "target_spread_arg", mt_ref_arg); + result = (int) mh_spreadInvoker.invokeExact(mh_spread_target, (Object[]) null); + } catch(NullPointerException e) { + // Expected exception - do nothing! + } catch(Throwable e) { + throw new Error(e); + } + + if (result != 42) throw new Error("Expected NullPointerException was not thrown"); + } + + public static int target_spread_arg(Integer i1) { + return i1.intValue(); + } + +}
--- a/jaxp/.hgtags Thu Feb 02 09:39:33 2012 -0800 +++ b/jaxp/.hgtags Wed Jul 05 18:01:59 2017 +0200 @@ -145,3 +145,4 @@ d41eeadf5c1344b88c5051a997aec9e1ad7ce1db jdk8-b21 cf9d6ec44f891236ad18451021d6dcd57dc82f7b jdk8-b22 95102fd334183d15dc98a95dd0d749527b6c7300 jdk8-b23 +7836655e2495646c462f13de73dcc3ada197b64f jdk8-b24
--- a/jdk/.hgtags Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/.hgtags Wed Jul 05 18:01:59 2017 +0200 @@ -145,3 +145,4 @@ 664fa4fb0ee411ef048903c479f8b962fcdb2f4b jdk8-b21 dda27c73d8db4a9c7a23872b6f0c5106edcb2021 jdk8-b22 54202e0148ec7d4570cab5bc9b00d216a7677569 jdk8-b23 +34029a0c69bba882264a29fc822f8283fd15f104 jdk8-b24
--- a/jdk/make/com/oracle/Makefile Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/make/com/oracle/Makefile Wed Jul 05 18:01:59 2017 +0200 @@ -38,8 +38,14 @@ endif endif +JFR = +ifndef OPENJDK +ifndef JAVASE_EMBEDDED + JFR = jfr +endif +endif -SUBDIRS = net nio util $(UCRYPTO) +SUBDIRS = $(JFR) net nio util $(UCRYPTO) include $(BUILDDIR)/common/Subdirs.gmk
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/com/oracle/jfr/Makefile Wed Jul 05 18:01:59 2017 +0200 @@ -0,0 +1,73 @@ +# +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute 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. +# + +BUILDDIR = ../../.. +PACKAGE = oracle.jrockit.jfr +LIBRARY = jfr +PRODUCT = oracle +include $(BUILDDIR)/common/Defs.gmk + +# +# Use mapfile +# +FILES_m = $(CLOSED_SHARE_SRC)/native/oracle/jfr/mapfile-vers +include $(BUILDDIR)/common/Mapfile-vers.gmk + +# +# Files to compile +# +FILES_c = VMJFR.c + +AUTO_FILES_JAVA_DIRS = com/oracle/jrockit/jfr oracle/jrockit/jfr + +# Find C source files +# +vpath %.c $(CLOSED_SHARE_SRC)/native/oracle/jfr + +# +# Library to compile. +# +include $(BUILDDIR)/common/Library.gmk + +JVMLIB = +JAVALIB = +OTHER_LDLIBS = + +clean clobber:: + $(RM) -r $(CLASSDESTDIR)/com/oracle/jrockit/jfr + $(RM) -r $(CLASSDESTDIR)/oracle/jrockit/jfr + + +# Copy pre-shipped .jfs files +JFR_LIBDIR = $(LIBDIR)/jfr +JFR_SRCDIR = $(CLOSED_SHARE_SRC)/lib/jfr + +$(JFR_LIBDIR)/%.jfs: $(JFR_SRCDIR)/%.jfs + $(install-file) + +JFS_FILES := $(subst $(JFR_SRCDIR),$(JFR_LIBDIR),$(wildcard $(JFR_SRCDIR)/*.jfs)) + +all build : $(JFS_FILES) +
--- a/jdk/make/common/Defs.gmk Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/make/common/Defs.gmk Wed Jul 05 18:01:59 2017 +0200 @@ -425,7 +425,12 @@ # namely jni.h, jvm.h, and jni_utils.h, plus their platform-specific # relatives. # -VPATH.h = $(PLATFORM_SRC)/javavm/export$(CLASSPATH_SEPARATOR)$(SHARE_SRC)/javavm/export +VPATH0.h = $(PLATFORM_SRC)/javavm/export$(CLASSPATH_SEPARATOR)$(SHARE_SRC)/javavm/export +ifdef OPENJDK + VPATH.h = $(VPATH0.h) +else + VPATH.h = $(CLOSED_SHARE_SRC)/javavm/export$(CLASSPATH_SEPARATOR)$(VPATH0.h) +endif vpath %.h $(VPATH.h) #
--- a/jdk/make/common/Release-embedded.gmk Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/make/common/Release-embedded.gmk Wed Jul 05 18:01:59 2017 +0200 @@ -189,7 +189,7 @@ $(RM) -r $(JRE_REDUCED_HEADLESS_IMAGE_DIR)/lib/audio $(RM) -fr $(JRE_REDUCED_HEADLESS_IMAGE_DIR)/lib/applet $(RM) $(JRE_REDUCED_HEADLESS_IMAGE_DIR)/lib/$(LIBARCH)/awt_robot - $(RM) -r $(JRE_REDUCED_HEADLESS_IMAGE_DIR)/lib/$(LIBARCH)/xawt + $(RM) $(JRE_REDUCED_HEADLESS_IMAGE_DIR)/lib/$(LIBARCH)/libawt_xawt.so $(RM) -r $(JRE_REDUCED_HEADLESS_IMAGE_DIR)/lib/$(LIBARCH)/libsplashscreen.so @# Remove oblique fonts and reduce font support to LucidaSansRegular only $(RM) -fr $(JRE_REDUCED_HEADLESS_IMAGE_DIR)/lib/oblique-fonts
--- a/jdk/make/common/Release.gmk Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/make/common/Release.gmk Wed Jul 05 18:01:59 2017 +0200 @@ -381,6 +381,11 @@ sun/tools/jinfo \ sun/tools/jmap +# classes that go into jfr.jar +JFR_CLASSES_DIRS= \ + com/oracle/jrockit/jfr \ + oracle/jrockit/jfr + # classes that go into jsse.jar JSSE_CLASSES_DIRS = \ sun/security/provider/Sun.class \ @@ -583,6 +588,23 @@ $(ECHO) "sun/tools/jstack/" >> $@ $(ECHO) "sun/tools/jinfo/" >> $@ $(ECHO) "sun/tools/jmap/" >> $@ +ifndef OPENJDK +ifndef JAVASE_EMBEDDED + $(ECHO) "com/oracle/jrockit/jfr/" >> $@ + $(ECHO) "com/oracle/jrockit/jfr/client/" >> $@ + $(ECHO) "com/oracle/jrockit/jfr/management/" >> $@ + $(ECHO) "oracle/jrockit/jfr/" >> $@ + $(ECHO) "oracle/jrockit/jfr/events/" >> $@ + $(ECHO) "oracle/jrockit/jfr/openmbean/" >> $@ + $(ECHO) "oracle/jrockit/jfr/parser/" >> $@ + $(ECHO) "oracle/jrockit/jfr/settings/" >> $@ + $(ECHO) "oracle/jrockit/jfr/tools/" >> $@ + $(ECHO) "oracle/jrockit/jfr/util/" >> $@ + $(ECHO) "oracle/jrockit/jfr/util/log/" >> $@ + $(ECHO) "oracle/jrockit/jfr/util/os/" >> $@ + $(ECHO) "oracle/jrockit/jfr/util/text/" >> $@ +endif +endif # File order list for rt.jar @@ -607,6 +629,20 @@ $(MV) $@.temp $@ @($(CD) $(CLASSBINDIR) && $(java-vm-cleanup)) +# Create the jfr.jar containing Java Flight Recorder implementation +JFR_JAR= +ifndef OPENJDK +ifndef JAVASE_EMBEDDED +JFR_JAR=$(ABS_TEMPDIR)/jfr-orig.jar +$(JFR_JAR): $(OTHER_JAR_MANIFEST_FILE) + $(prep-target) + $(CD) $(CLASSBINDIR) && \ + $(BOOT_JAR_CMD) $(CREATE_JAR_OPTS) $(OTHER_JAR_MANIFEST_FILE) $@ \ + $(JFR_CLASSES_DIRS) $(BOOT_JAR_JFLAGS) + @$(CD) $(CLASSBINDIR) && $(java-vm-cleanup) +endif +endif + # Create the rt.jar file list & non-class files list JARSPLIT_JARFILE = $(BUILDTOOLJARDIR)/jarsplit.jar @@ -741,7 +777,7 @@ # drive names like C: initial-image-jre:: initial-image-jre-setup \ $(JRE_DOCFILES) \ - $(RT_JAR) $(RESOURCES_JAR) $(JSSE_JAR) \ + $(RT_JAR) $(RESOURCES_JAR) $(JSSE_JAR) $(JFR_JAR) \ $(BUILDMETAINDEX_JARFILE) @# Copy in bin directory $(CD) $(OUTPUTDIR) && $(FIND) bin -depth | $(CPIO) -pdum $(JRE_IMAGE_DIR) @@ -769,6 +805,9 @@ $(CP) $(RT_JAR) $(JRE_IMAGE_DIR)/lib/rt.jar $(CP) $(RESOURCES_JAR) $(JRE_IMAGE_DIR)/lib/resources.jar $(CP) $(JSSE_JAR) $(JRE_IMAGE_DIR)/lib/jsse.jar +ifneq ($(JFR_JAR),) + $(CP) $(JFR_JAR) $(JRE_IMAGE_DIR)/lib/jfr.jar +endif @# Generate meta-index to make boot and extension class loaders lazier $(CD) $(JRE_IMAGE_DIR)/lib && \ $(BOOT_JAVA_CMD) -jar $(BUILDMETAINDEX_JARFILE) \
--- a/jdk/make/jprt.properties Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/make/jprt.properties Wed Jul 05 18:01:59 2017 +0200 @@ -62,18 +62,32 @@ # Default jdk test targets (testset=default) jprt.make.rule.default.test.targets= \ - ${jprt.my.test.target.set:TESTNAME=jdk_beans1}, \ + ${jprt.my.test.target.set:TESTNAME=jdk_lang}, \ + ${jprt.my.test.target.set:TESTNAME=jdk_math} + +# Default vm test targets (testset=core) +jprt.vm.core.test.targets= \ + ${jprt.vm.default.test.targets} + +# Core jdk test targets (testset=core) +jprt.make.rule.core.test.targets= \ + ${jprt.make.rule.default.test.targets}, \ + ${jprt.my.test.target.set:TESTNAME=jdk_util}, \ ${jprt.my.test.target.set:TESTNAME=jdk_io}, \ - ${jprt.my.test.target.set:TESTNAME=jdk_lang}, \ - ${jprt.my.test.target.set:TESTNAME=jdk_math}, \ - ${jprt.my.test.target.set:TESTNAME=jdk_misc}, \ ${jprt.my.test.target.set:TESTNAME=jdk_net}, \ ${jprt.my.test.target.set:TESTNAME=jdk_nio1}, \ ${jprt.my.test.target.set:TESTNAME=jdk_nio2}, \ ${jprt.my.test.target.set:TESTNAME=jdk_nio3}, \ ${jprt.my.test.target.set:TESTNAME=jdk_security1}, \ + ${jprt.my.test.target.set:TESTNAME=jdk_security2}, \ + ${jprt.my.test.target.set:TESTNAME=jdk_security3}, \ + ${jprt.my.test.target.set:TESTNAME=jdk_rmi}, \ + ${jprt.my.test.target.set:TESTNAME=jdk_management1}, \ + ${jprt.my.test.target.set:TESTNAME=jdk_management2}, \ ${jprt.my.test.target.set:TESTNAME=jdk_text}, \ - ${jprt.my.test.target.set:TESTNAME=jdk_util} + ${jprt.my.test.target.set:TESTNAME=jdk_tools1}, \ + ${jprt.my.test.target.set:TESTNAME=jdk_tools2}, \ + ${jprt.my.test.target.set:TESTNAME=jdk_misc} # All vm test targets (testset=all) jprt.vm.all.test.targets= \ @@ -83,19 +97,13 @@ # All jdk test targets (testset=all) jprt.make.rule.all.test.targets= \ - ${jprt.make.rule.default.test.targets}, \ + ${jprt.make.rule.core.test.targets}, \ ${jprt.my.test.target.set:TESTNAME=jdk_awt}, \ + ${jprt.my.test.target.set:TESTNAME=jdk_beans1}, \ ${jprt.my.test.target.set:TESTNAME=jdk_beans2}, \ ${jprt.my.test.target.set:TESTNAME=jdk_beans3}, \ - ${jprt.my.test.target.set:TESTNAME=jdk_management1}, \ - ${jprt.my.test.target.set:TESTNAME=jdk_management2}, \ - ${jprt.my.test.target.set:TESTNAME=jdk_rmi}, \ - ${jprt.my.test.target.set:TESTNAME=jdk_security2}, \ - ${jprt.my.test.target.set:TESTNAME=jdk_security3}, \ ${jprt.my.test.target.set:TESTNAME=jdk_sound}, \ - ${jprt.my.test.target.set:TESTNAME=jdk_swing}, \ - ${jprt.my.test.target.set:TESTNAME=jdk_tools1}, \ - ${jprt.my.test.target.set:TESTNAME=jdk_tools2} + ${jprt.my.test.target.set:TESTNAME=jdk_swing} # JCK test targets in test/Makefile (no windows) jprt.my.jck.test.target.set= \
--- a/jdk/make/sun/font/Makefile Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/make/sun/font/Makefile Wed Jul 05 18:01:59 2017 +0200 @@ -175,7 +175,7 @@ ifeq ($(PLATFORM), solaris) # Note that on Solaris, fontmanager is built against the headless library. LDFLAGS += -L$(LIBDIR)/$(LIBARCH)/headless - OTHER_LDLIBS += -lawt -L$(LIBDIR)/$(LIBARCH)/xawt -lmawt -lc $(LIBM) $(LIBCXX) + OTHER_LDLIBS += -lawt -lawt_xawt -lc $(LIBM) $(LIBCXX) else # PLATFORM is linux OTHER_LDLIBS += -lawt $(LIBM) $(LIBCXX) ifeq ("$(CC_VER_MAJOR)", "3")
--- a/jdk/make/sun/font/t2k/Makefile Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/make/sun/font/t2k/Makefile Wed Jul 05 18:01:59 2017 +0200 @@ -99,7 +99,7 @@ endif else ifeq ($(PLATFORM), solaris) - OTHER_LDLIBS += -lawt -L$(LIBDIR)/$(LIBARCH)/xawt -lmawt + OTHER_LDLIBS += -lawt -lawt_xawt endif endif endif
--- a/jdk/make/sun/headless/Makefile Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/make/sun/headless/Makefile Wed Jul 05 18:01:59 2017 +0200 @@ -28,11 +28,9 @@ NO_ROBOT = true MOTIF_VERSION = none MOTIF_VERSION_STRING=none -LIB_LOCATION = $(LIBDIR)/$(LIBARCH)/headless PACKAGE = sun.awt -LIBRARY = mawt -LIBRARY_OUTPUT = headless +LIBRARY = awt_headless PRODUCT = sun include $(BUILDDIR)/common/Defs.gmk
--- a/jdk/make/sun/jawt/Makefile Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/make/sun/jawt/Makefile Wed Jul 05 18:01:59 2017 +0200 @@ -113,17 +113,17 @@ # ifeq ($(PLATFORM), solaris) ifndef BUILD_HEADLESS_ONLY - OTHER_LDLIBS = -L$(LIBDIR)/$(LIBARCH) -L$(OPENWIN_LIB) -L$(LIBDIR)/$(LIBARCH)/xawt -lmawt -L/usr/openwin/sfw/lib$(ISA_DIR) -lXrender + OTHER_LDLIBS = -L$(LIBDIR)/$(LIBARCH) -L$(OPENWIN_LIB) -lawt_xawt -L/usr/openwin/sfw/lib$(ISA_DIR) -lXrender else - OTHER_LDLIBS = -L$(LIBDIR)/$(LIBARCH) -L$(OPENWIN_LIB) -L$(LIBDIR)/$(LIBARCH)/headless -lmawt -L/usr/openwin/sfw/lib$(ISA_DIR) -lXrender + OTHER_LDLIBS = -L$(LIBDIR)/$(LIBARCH) -L$(OPENWIN_LIB) -lawt_headless -L/usr/openwin/sfw/lib$(ISA_DIR) -lXrender endif endif # PLATFORM ifeq ($(PLATFORM), linux) ifndef BUILD_HEADLESS_ONLY - OTHER_LDLIBS = -L$(LIBDIR)/$(LIBARCH) -lawt -L$(LIBDIR)/$(LIBARCH)/xawt -lmawt + OTHER_LDLIBS = -L$(LIBDIR)/$(LIBARCH) -lawt -lawt_xawt else - OTHER_LDLIBS = -L$(LIBDIR)/$(LIBARCH) -lawt -L$(LIBDIR)/$(LIBARCH)/headless -lmawt + OTHER_LDLIBS = -L$(LIBDIR)/$(LIBARCH) -lawt -lawt_headless CFLAGS += -DHEADLESS endif endif # PLATFORM
--- a/jdk/make/sun/xawt/Makefile Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/make/sun/xawt/Makefile Wed Jul 05 18:01:59 2017 +0200 @@ -25,9 +25,7 @@ BUILDDIR = ../.. PACKAGE = sun.awt.X11 -LIBRARY = mawt -LIBRARY_OUTPUT = xawt -LIB_LOCATION = $(LIBDIR)/$(LIBARCH)/xawt +LIBRARY = awt_xawt PRODUCT = sun include $(BUILDDIR)/common/Defs.gmk
--- a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath2Filter.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath2Filter.java Wed Jul 05 18:01:59 2017 +0200 @@ -148,8 +148,8 @@ } - input.addNodeFilter(new XPath2NodeFilter(convertNodeListToSet(unionNodes), - convertNodeListToSet(substractNodes),convertNodeListToSet(intersectNodes))); + input.addNodeFilter(new XPath2NodeFilter(unionNodes, substractNodes, + intersectNodes)); input.setNodeSet(true); return input; } catch (TransformerException ex) { @@ -170,32 +170,20 @@ throw new TransformationException("empty", ex); } } - static Set<Node> convertNodeListToSet(List<NodeList> l){ - Set<Node> result=new HashSet<Node>(); - - for (NodeList rootNodes : l) { - int length = rootNodes.getLength(); - for (int i = 0; i < length; i++) { - Node rootNode = rootNodes.item(i); - result.add(rootNode); - } - } - return result; - } } class XPath2NodeFilter implements NodeFilter { - boolean hasUnionNodes; - boolean hasSubstractNodes; - boolean hasIntersectNodes; - XPath2NodeFilter(Set<Node> unionNodes, Set<Node> substractNodes, - Set<Node> intersectNodes) { - this.unionNodes=unionNodes; - hasUnionNodes=!unionNodes.isEmpty(); - this.substractNodes=substractNodes; - hasSubstractNodes=!substractNodes.isEmpty(); - this.intersectNodes=intersectNodes; - hasIntersectNodes=!intersectNodes.isEmpty(); + boolean hasUnionFilter; + boolean hasSubstractFilter; + boolean hasIntersectFilter; + XPath2NodeFilter(List<NodeList> unionNodes, List<NodeList> substractNodes, + List<NodeList> intersectNodes) { + hasUnionFilter=!unionNodes.isEmpty(); + this.unionNodes=convertNodeListToSet(unionNodes); + hasSubstractFilter=!substractNodes.isEmpty(); + this.substractNodes=convertNodeListToSet(substractNodes); + hasIntersectFilter=!intersectNodes.isEmpty(); + this.intersectNodes=convertNodeListToSet(intersectNodes); } Set<Node> unionNodes; Set<Node> substractNodes; @@ -208,16 +196,16 @@ public int isNodeInclude(Node currentNode) { int result=1; - if (hasSubstractNodes && rooted(currentNode, substractNodes)) { + if (hasSubstractFilter && rooted(currentNode, substractNodes)) { result = -1; - } else if (hasIntersectNodes && !rooted(currentNode, intersectNodes)) { + } else if (hasIntersectFilter && !rooted(currentNode, intersectNodes)) { result = 0; } //TODO OPTIMIZE if (result==1) return 1; - if (hasUnionNodes) { + if (hasUnionFilter) { if (rooted(currentNode, unionNodes)) { return 1; } @@ -231,7 +219,7 @@ int inUnion=-1; public int isNodeIncludeDO(Node n, int level) { int result=1; - if (hasSubstractNodes) { + if (hasSubstractFilter) { if ((inSubstract==-1) || (level<=inSubstract)) { if (inList(n, substractNodes)) { inSubstract=level; @@ -244,7 +232,7 @@ } } if (result!=-1){ - if (hasIntersectNodes) { + if (hasIntersectFilter) { if ((inIntersect==-1) || (level<=inIntersect)) { if (!inList(n, intersectNodes)) { inIntersect=-1; @@ -260,7 +248,7 @@ inUnion=-1; if (result==1) return 1; - if (hasUnionNodes) { + if (hasUnionFilter) { if ((inUnion==-1) && inList(n, unionNodes)) { inUnion=level; } @@ -280,6 +268,9 @@ * @return if rooted bye the rootnodes */ static boolean rooted(Node currentNode, Set<Node> nodeList ) { + if (nodeList.isEmpty()) { + return false; + } if (nodeList.contains(currentNode)) { return true; } @@ -302,4 +293,17 @@ static boolean inList(Node currentNode, Set<Node> nodeList ) { return nodeList.contains(currentNode); } + + private static Set<Node> convertNodeListToSet(List<NodeList> l){ + Set<Node> result=new HashSet<Node>(); + + for (NodeList rootNodes : l) { + int length = rootNodes.getLength(); + for (int i = 0; i < length; i++) { + Node rootNode = rootNodes.item(i); + result.add(rootNode); + } + } + return result; + } }
--- a/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/com/sun/rowset/CachedRowSetImpl.java Wed Jul 05 18:01:59 2017 +0200 @@ -6431,7 +6431,8 @@ * @see #setKeyColumns */ public int[] getKeyColumns() throws SQLException { - return keyCols; + int[]keyColumns = this.keyCols; + return (keyColumns == null) ? null : Arrays.copyOf(keyColumns, keyColumns.length); }
--- a/jdk/src/share/classes/com/sun/rowset/internal/BaseRow.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/com/sun/rowset/internal/BaseRow.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -27,6 +27,7 @@ import java.sql.*; import java.io.*; +import java.util.Arrays; /** * The abstract base class from which the classes <code>Row</code> @@ -65,7 +66,8 @@ * original values */ public Object[] getOrigRow() { - return origVals; + Object[] origRow = this.origVals; + return (origRow == null) ? null: Arrays.copyOf(origRow, origRow.length); } /**
--- a/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlWriter.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -48,7 +48,7 @@ * for this field is set with the <code>java.io.Writer</code> object given * as the second argument to the <code>writeXML</code> method. */ - private java.io.Writer writer; + private transient java.io.Writer writer; /** * The <code>java.util.Stack</code> object that this <code>WebRowSetXmlWriter</code> @@ -205,16 +205,11 @@ //Changed to beginSection and endSection for maps for proper indentation beginSection("map"); - java.util.Map<?,?> typeMap = caller.getTypeMap(); - if (typeMap != null) { - Iterator<?> i = typeMap.keySet().iterator(); - Class<?> c; - String type; - while (i.hasNext()) { - type = (String)i.next(); - c = (Class)typeMap.get(type); - propString("type", type); - propString("class", c.getName()); + Map<String, Class<?>> typeMap = caller.getTypeMap(); + if(typeMap != null) { + for(Map.Entry<String, Class<?>> mm : typeMap.entrySet()) { + propString("type", mm.getKey()); + propString("class", mm.getValue().getName()); } } endSection("map");
--- a/jdk/src/share/classes/java/awt/datatransfer/MimeType.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/java/awt/datatransfer/MimeType.java Wed Jul 05 18:01:59 2017 +0200 @@ -30,6 +30,7 @@ import java.io.ObjectInput; import java.io.IOException; import java.util.Enumeration; +import java.util.Locale; /** @@ -93,14 +94,14 @@ MimeTypeParseException { // check to see if primary is valid if(isValidToken(primary)) { - primaryType = primary.toLowerCase(); + primaryType = primary.toLowerCase(Locale.ENGLISH); } else { throw new MimeTypeParseException("Primary type is invalid."); } // check to see if sub is valid if(isValidToken(sub)) { - subType = sub.toLowerCase(); + subType = sub.toLowerCase(Locale.ENGLISH); } else { throw new MimeTypeParseException("Sub type is invalid."); } @@ -158,17 +159,17 @@ throw new MimeTypeParseException("Unable to find a sub type."); } else if((slashIndex >= 0) && (semIndex < 0)) { // we have a primary and sub type but no parameter list - primaryType = rawdata.substring(0, -slashIndex).trim().toLowerCase(); - subType = rawdata.substring(slashIndex + -1).trim().toLowerCase(); + primaryType = rawdata.substring(0,slashIndex). + trim().toLowerCase(Locale.ENGLISH); + subType = rawdata.substring(slashIndex + 1). + trim().toLowerCase(Locale.ENGLISH); parameters = new MimeTypeParameterList(); } else if (slashIndex < semIndex) { // we have all three items in the proper sequence - primaryType = rawdata.substring(0, -slashIndex).trim().toLowerCase(); + primaryType = rawdata.substring(0, slashIndex). + trim().toLowerCase(Locale.ENGLISH); subType = rawdata.substring(slashIndex + 1, -semIndex).trim().toLowerCase(); + semIndex).trim().toLowerCase(Locale.ENGLISH); parameters = new MimeTypeParameterList(rawdata.substring(semIndex)); } else {
--- a/jdk/src/share/classes/java/awt/event/MouseEvent.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/java/awt/event/MouseEvent.java Wed Jul 05 18:01:59 2017 +0200 @@ -758,7 +758,6 @@ if (getModifiersEx() != 0) { //There is at least one more button in a pressed state. if (id == MouseEvent.MOUSE_RELEASED || id == MouseEvent.MOUSE_CLICKED){ - System.out.println("MEvent. CASE!"); shouldExcludeButtonFromExtModifiers = true; } }
--- a/jdk/src/share/classes/java/beans/BeanInfo.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/java/beans/BeanInfo.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -25,134 +25,134 @@ package java.beans; +import java.awt.Image; + /** - * A bean implementor who wishes to provide explicit information about - * their bean may provide a BeanInfo class that implements this BeanInfo - * interface and provides explicit information about the methods, - * properties, events, etc, of their bean. + * Use the {@code BeanInfo} interface + * to create a {@code BeanInfo} class + * and provide explicit information about the methods, + * properties, events, and other features of your beans. * <p> - * A bean implementor doesn't need to provide a complete set of - * explicit information. You can pick and choose which information - * you want to provide and the rest will be obtained by automatic - * analysis using low-level reflection of the bean classes' methods + * When developing your bean, you can implement + * the bean features required for your application task + * omitting the rest of the {@code BeanInfo} features. + * They will be obtained through the automatic analysis + * by using the low-level reflection of the bean methods * and applying standard design patterns. + * You have an opportunity to provide additional bean information + * through various descriptor classes. * <p> - * You get the opportunity to provide lots and lots of different - * information as part of the various XyZDescriptor classes. But - * don't panic, you only really need to provide the minimal core - * information required by the various constructors. - * <P> - * See also the SimpleBeanInfo class which provides a convenient - * "noop" base class for BeanInfo classes, which you can override - * for those specific places where you want to return explicit info. - * <P> - * To learn about all the behaviour of a bean see the Introspector class. + * See the {@link SimpleBeanInfo} class that is + * a convenient basic class for {@code BeanInfo} classes. + * You can override the methods and properties of + * the {@code SimpleBeanInfo} class to define specific information. + * <p> + * See also the {@link Introspector} class to learn more about bean behavior. */ - public interface BeanInfo { /** - * Gets the beans <code>BeanDescriptor</code>. + * Returns the bean descriptor + * that provides overall information about the bean, + * such as its display name or its customizer. * - * @return A BeanDescriptor providing overall information about - * the bean, such as its displayName, its customizer, etc. May - * return null if the information should be obtained by automatic - * analysis. + * @return a {@link BeanDescriptor} object, + * or {@code null} if the information is to + * be obtained through the automatic analysis */ BeanDescriptor getBeanDescriptor(); /** - * Gets the beans <code>EventSetDescriptor</code>s. + * Returns the event descriptors of the bean + * that define the types of events fired by this bean. * - * @return An array of EventSetDescriptors describing the kinds of - * events fired by this bean. May return null if the information - * should be obtained by automatic analysis. + * @return an array of {@link EventSetDescriptor} objects, + * or {@code null} if the information is to + * be obtained through the automatic analysis */ EventSetDescriptor[] getEventSetDescriptors(); /** - * A bean may have a "default" event that is the event that will - * mostly commonly be used by humans when using the bean. - * @return Index of default event in the EventSetDescriptor array - * returned by getEventSetDescriptors. - * <P> Returns -1 if there is no default event. + * A bean may have a default event typically applied when this bean is used. + * + * @return index of the default event in the {@code EventSetDescriptor} array + * returned by the {@code getEventSetDescriptors} method, + * or -1 if there is no default event */ int getDefaultEventIndex(); /** * Returns descriptors for all properties of the bean. - * May return {@code null} if the information - * should be obtained by automatic analysis. * <p> * If a property is indexed, then its entry in the result array - * will belong to the {@link IndexedPropertyDescriptor} subclass + * belongs to the {@link IndexedPropertyDescriptor} subclass * of the {@link PropertyDescriptor} class. * A client of the {@code getPropertyDescriptors} method - * can use "{@code instanceof}" to check + * can use the {@code instanceof} operator to check * whether a given {@code PropertyDescriptor} * is an {@code IndexedPropertyDescriptor}. * - * @return an array of {@code PropertyDescriptor}s - * describing all properties supported by the bean - * or {@code null} + * @return an array of {@code PropertyDescriptor} objects, + * or {@code null} if the information is to + * be obtained through the automatic analysis */ PropertyDescriptor[] getPropertyDescriptors(); /** - * A bean may have a "default" property that is the property that will - * mostly commonly be initially chosen for update by human's who are - * customizing the bean. - * @return Index of default property in the PropertyDescriptor array - * returned by getPropertyDescriptors. - * <P> Returns -1 if there is no default property. + * A bean may have a default property commonly updated when this bean is customized. + * + * @return index of the default property in the {@code PropertyDescriptor} array + * returned by the {@code getPropertyDescriptors} method, + * or -1 if there is no default property */ int getDefaultPropertyIndex(); /** - * Gets the beans <code>MethodDescriptor</code>s. + * Returns the method descriptors of the bean + * that define the externally visible methods supported by this bean. * - * @return An array of MethodDescriptors describing the externally - * visible methods supported by this bean. May return null if - * the information should be obtained by automatic analysis. + * @return an array of {@link MethodDescriptor} objects, + * or {@code null} if the information is to + * be obtained through the automatic analysis */ MethodDescriptor[] getMethodDescriptors(); /** - * This method allows a BeanInfo object to return an arbitrary collection - * of other BeanInfo objects that provide additional information on the - * current bean. - * <P> - * If there are conflicts or overlaps between the information provided - * by different BeanInfo objects, then the current BeanInfo takes precedence - * over the getAdditionalBeanInfo objects, and later elements in the array - * take precedence over earlier ones. + * This method enables the current {@code BeanInfo} object + * to return an arbitrary collection of other {@code BeanInfo} objects + * that provide additional information about the current bean. + * <p> + * If there are conflicts or overlaps between the information + * provided by different {@code BeanInfo} objects, + * the current {@code BeanInfo} object takes priority + * over the additional {@code BeanInfo} objects. + * Array elements with higher indices take priority + * over the elements with lower indices. * - * @return an array of BeanInfo objects. May return null. + * @return an array of {@code BeanInfo} objects, + * or {@code null} if there are no additional {@code BeanInfo} objects */ BeanInfo[] getAdditionalBeanInfo(); /** - * This method returns an image object that can be used to - * represent the bean in toolboxes, toolbars, etc. Icon images - * will typically be GIFs, but may in future include other formats. + * Returns an image that can be used to represent the bean in toolboxes or toolbars. * <p> - * Beans aren't required to provide icons and may return null from - * this method. - * <p> - * There are four possible flavors of icons (16x16 color, - * 32x32 color, 16x16 mono, 32x32 mono). If a bean choses to only - * support a single icon we recommend supporting 16x16 color. - * <p> - * We recommend that icons have a "transparent" background - * so they can be rendered onto an existing background. + * There are four possible types of icons: + * 16 x 16 color, 32 x 32 color, 16 x 16 mono, and 32 x 32 mono. + * If you implement a bean so that it supports a single icon, + * it is recommended to use 16 x 16 color. + * Another recommendation is to set a transparent background for the icons. * - * @param iconKind The kind of icon requested. This should be - * one of the constant values ICON_COLOR_16x16, ICON_COLOR_32x32, - * ICON_MONO_16x16, or ICON_MONO_32x32. - * @return An image object representing the requested icon. May - * return null if no suitable icon is available. + * @param iconKind the kind of icon requested + * @return an image object representing the requested icon, + * or {@code null} if no suitable icon is available + * + * @see #ICON_COLOR_16x16 + * @see #ICON_COLOR_32x32 + * @see #ICON_MONO_16x16 + * @see #ICON_MONO_32x32 */ - java.awt.Image getIcon(int iconKind); + Image getIcon(int iconKind); /** * Constant to indicate a 16 x 16 color icon.
--- a/jdk/src/share/classes/java/beans/Introspector.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/java/beans/Introspector.java Wed Jul 05 18:01:59 2017 +0200 @@ -473,7 +473,7 @@ // Now analyze each method. for (int i = 0; i < methodList.length; i++) { Method method = methodList[i]; - if (method == null || method.isSynthetic()) { + if (method == null) { continue; } // skip static methods.
--- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java Wed Jul 05 18:01:59 2017 +0200 @@ -559,7 +559,7 @@ // Normally give priority to y's readMethod. try { - if (yr != null && yr.getDeclaringClass() == getClass0()) { + if (isAssignable(xr, yr)) { setReadMethod(yr); } else { setReadMethod(xr); @@ -713,4 +713,37 @@ appendTo(sb, "readMethod", this.readMethodRef); appendTo(sb, "writeMethod", this.writeMethodRef); } + + private boolean isAssignable(Method m1, Method m2) { + if (m1 == null) { + return true; // choose second method + } + if (m2 == null) { + return false; // choose first method + } + if (!m1.getName().equals(m2.getName())) { + return true; // choose second method by default + } + Class<?> type1 = m1.getDeclaringClass(); + Class<?> type2 = m2.getDeclaringClass(); + if (!type1.isAssignableFrom(type2)) { + return false; // choose first method: it declared later + } + type1 = getReturnType(getClass0(), m1); + type2 = getReturnType(getClass0(), m2); + if (!type1.isAssignableFrom(type2)) { + return false; // choose first method: it overrides return type + } + Class<?>[] args1 = getParameterTypes(getClass0(), m1); + Class<?>[] args2 = getParameterTypes(getClass0(), m2); + if (args1.length != args2.length) { + return true; // choose second method by default + } + for (int i = 0; i < args1.length; i++) { + if (!args1[i].isAssignableFrom(args2[i])) { + return false; // choose first method: it overrides parameter + } + } + return true; // choose second method + } }
--- a/jdk/src/share/classes/java/io/DataInput.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/java/io/DataInput.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -26,12 +26,12 @@ package java.io; /** - * The <code>DataInput</code> interface provides + * The {@code DataInput} interface provides * for reading bytes from a binary stream and * reconstructing from them data in any of * the Java primitive types. There is also * a - * facility for reconstructing a <code>String</code> + * facility for reconstructing a {@code String} * from data in * <a href="#modified-utf-8">modified UTF-8</a> * format. @@ -39,12 +39,12 @@ * It is generally true of all the reading * routines in this interface that if end of * file is reached before the desired number - * of bytes has been read, an <code>EOFException</code> - * (which is a kind of <code>IOException</code>) + * of bytes has been read, an {@code EOFException} + * (which is a kind of {@code IOException}) * is thrown. If any byte cannot be read for - * any reason other than end of file, an <code>IOException</code> - * other than <code>EOFException</code> is - * thrown. In particular, an <code>IOException</code> + * any reason other than end of file, an {@code IOException} + * other than {@code EOFException} is + * thrown. In particular, an {@code IOException} * may be thrown if the input stream has been * closed. * @@ -58,8 +58,8 @@ * Note that in the following tables, the most significant bit appears in the * far left-hand column. * <p> - * All characters in the range <code>'\u0001'</code> to - * <code>'\u007F'</code> are represented by a single byte: + * All characters in the range {@code '\u005Cu0001'} to + * {@code '\u005Cu007F'} are represented by a single byte: * * <blockquote> * <table border="1" cellspacing="0" cellpadding="8" width="50%" @@ -83,8 +83,8 @@ * </blockquote> * * <p> - * The null character <code>'\u0000'</code> and characters in the - * range <code>'\u0080'</code> to <code>'\u07FF'</code> are + * The null character {@code '\u005Cu0000'} and characters in the + * range {@code '\u005Cu0080'} to {@code '\u005Cu07FF'} are * represented by a pair of bytes: * * <blockquote> @@ -123,8 +123,8 @@ * </blockquote> * * <br> - * <code>char</code> values in the range <code>'\u0800'</code> to - * <code>'\uFFFF'</code> are represented by three bytes: + * {@code char} values in the range {@code '\u005Cu0800'} to + * {@code '\u005CuFFFF'} are represented by three bytes: * * <blockquote> * <table border="1" cellspacing="0" cellpadding="8" width="50%" @@ -178,7 +178,7 @@ * The differences between this format and the * standard UTF-8 format are the following: * <ul> - * <li>The null byte <code>'\u0000'</code> is encoded in 2-byte format + * <li>The null byte {@code '\u005Cu0000'} is encoded in 2-byte format * rather than 1-byte, so that the encoded strings never have * embedded nulls. * <li>Only the 1-byte, 2-byte, and 3-byte formats are used. @@ -195,36 +195,36 @@ /** * Reads some bytes from an input * stream and stores them into the buffer - * array <code>b</code>. The number of bytes + * array {@code b}. The number of bytes * read is equal - * to the length of <code>b</code>. + * to the length of {@code b}. * <p> * This method blocks until one of the * following conditions occurs:<p> * <ul> - * <li><code>b.length</code> + * <li>{@code b.length} * bytes of input data are available, in which * case a normal return is made. * * <li>End of - * file is detected, in which case an <code>EOFException</code> + * file is detected, in which case an {@code EOFException} * is thrown. * * <li>An I/O error occurs, in - * which case an <code>IOException</code> other - * than <code>EOFException</code> is thrown. + * which case an {@code IOException} other + * than {@code EOFException} is thrown. * </ul> * <p> - * If <code>b</code> is <code>null</code>, - * a <code>NullPointerException</code> is thrown. - * If <code>b.length</code> is zero, then + * If {@code b} is {@code null}, + * a {@code NullPointerException} is thrown. + * If {@code b.length} is zero, then * no bytes are read. Otherwise, the first - * byte read is stored into element <code>b[0]</code>, - * the next one into <code>b[1]</code>, and + * byte read is stored into element {@code b[0]}, + * the next one into {@code b[1]}, and * so on. * If an exception is thrown from * this method, then it may be that some but - * not all bytes of <code>b</code> have been + * not all bytes of {@code b} have been * updated with data from the input stream. * * @param b the buffer into which the data is read. @@ -236,7 +236,7 @@ /** * - * Reads <code>len</code> + * Reads {@code len} * bytes from * an input stream. * <p> @@ -244,32 +244,32 @@ * blocks until one of the following conditions * occurs:<p> * <ul> - * <li><code>len</code> bytes + * <li>{@code len} bytes * of input data are available, in which case * a normal return is made. * * <li>End of file - * is detected, in which case an <code>EOFException</code> + * is detected, in which case an {@code EOFException} * is thrown. * * <li>An I/O error occurs, in - * which case an <code>IOException</code> other - * than <code>EOFException</code> is thrown. + * which case an {@code IOException} other + * than {@code EOFException} is thrown. * </ul> * <p> - * If <code>b</code> is <code>null</code>, - * a <code>NullPointerException</code> is thrown. - * If <code>off</code> is negative, or <code>len</code> - * is negative, or <code>off+len</code> is - * greater than the length of the array <code>b</code>, - * then an <code>IndexOutOfBoundsException</code> + * If {@code b} is {@code null}, + * a {@code NullPointerException} is thrown. + * If {@code off} is negative, or {@code len} + * is negative, or {@code off+len} is + * greater than the length of the array {@code b}, + * then an {@code IndexOutOfBoundsException} * is thrown. - * If <code>len</code> is zero, + * If {@code len} is zero, * then no bytes are read. Otherwise, the first - * byte read is stored into element <code>b[off]</code>, - * the next one into <code>b[off+1]</code>, + * byte read is stored into element {@code b[off]}, + * the next one into {@code b[off+1]}, * and so on. The number of bytes read is, - * at most, equal to <code>len</code>. + * at most, equal to {@code len}. * * @param b the buffer into which the data is read. * @param off an int specifying the offset into the data. @@ -282,7 +282,7 @@ /** * Makes an attempt to skip over - * <code>n</code> bytes + * {@code n} bytes * of data from the input * stream, discarding the skipped bytes. However, * it may skip @@ -290,10 +290,10 @@ * bytes, possibly zero. This may result from * any of a * number of conditions; reaching - * end of file before <code>n</code> bytes + * end of file before {@code n} bytes * have been skipped is * only one possibility. - * This method never throws an <code>EOFException</code>. + * This method never throws an {@code EOFException}. * The actual * number of bytes skipped is returned. * @@ -305,13 +305,13 @@ /** * Reads one input byte and returns - * <code>true</code> if that byte is nonzero, - * <code>false</code> if that byte is zero. + * {@code true} if that byte is nonzero, + * {@code false} if that byte is zero. * This method is suitable for reading - * the byte written by the <code>writeBoolean</code> - * method of interface <code>DataOutput</code>. + * the byte written by the {@code writeBoolean} + * method of interface {@code DataOutput}. * - * @return the <code>boolean</code> value read. + * @return the {@code boolean} value read. * @exception EOFException if this stream reaches the end before reading * all the bytes. * @exception IOException if an I/O error occurs. @@ -321,11 +321,11 @@ /** * Reads and returns one input byte. * The byte is treated as a signed value in - * the range <code>-128</code> through <code>127</code>, + * the range {@code -128} through {@code 127}, * inclusive. * This method is suitable for - * reading the byte written by the <code>writeByte</code> - * method of interface <code>DataOutput</code>. + * reading the byte written by the {@code writeByte} + * method of interface {@code DataOutput}. * * @return the 8-bit value read. * @exception EOFException if this stream reaches the end before reading @@ -336,16 +336,16 @@ /** * Reads one input byte, zero-extends - * it to type <code>int</code>, and returns + * it to type {@code int}, and returns * the result, which is therefore in the range - * <code>0</code> - * through <code>255</code>. + * {@code 0} + * through {@code 255}. * This method is suitable for reading - * the byte written by the <code>writeByte</code> - * method of interface <code>DataOutput</code> - * if the argument to <code>writeByte</code> + * the byte written by the {@code writeByte} + * method of interface {@code DataOutput} + * if the argument to {@code writeByte} * was intended to be a value in the range - * <code>0</code> through <code>255</code>. + * {@code 0} through {@code 255}. * * @return the unsigned 8-bit value read. * @exception EOFException if this stream reaches the end before reading @@ -356,8 +356,8 @@ /** * Reads two input bytes and returns - * a <code>short</code> value. Let <code>a</code> - * be the first byte read and <code>b</code> + * a {@code short} value. Let {@code a} + * be the first byte read and {@code b} * be the second byte. The value * returned * is: @@ -365,8 +365,8 @@ * </code></pre> * This method * is suitable for reading the bytes written - * by the <code>writeShort</code> method of - * interface <code>DataOutput</code>. + * by the {@code writeShort} method of + * interface {@code DataOutput}. * * @return the 16-bit value read. * @exception EOFException if this stream reaches the end before reading @@ -377,19 +377,19 @@ /** * Reads two input bytes and returns - * an <code>int</code> value in the range <code>0</code> - * through <code>65535</code>. Let <code>a</code> + * an {@code int} value in the range {@code 0} + * through {@code 65535}. Let {@code a} * be the first byte read and - * <code>b</code> + * {@code b} * be the second byte. The value returned is: * <p><pre><code>(((a & 0xff) << 8) | (b & 0xff)) * </code></pre> * This method is suitable for reading the bytes - * written by the <code>writeShort</code> method - * of interface <code>DataOutput</code> if - * the argument to <code>writeShort</code> + * written by the {@code writeShort} method + * of interface {@code DataOutput} if + * the argument to {@code writeShort} * was intended to be a value in the range - * <code>0</code> through <code>65535</code>. + * {@code 0} through {@code 65535}. * * @return the unsigned 16-bit value read. * @exception EOFException if this stream reaches the end before reading @@ -399,19 +399,19 @@ int readUnsignedShort() throws IOException; /** - * Reads two input bytes and returns a <code>char</code> value. - * Let <code>a</code> - * be the first byte read and <code>b</code> + * Reads two input bytes and returns a {@code char} value. + * Let {@code a} + * be the first byte read and {@code b} * be the second byte. The value * returned is: * <p><pre><code>(char)((a << 8) | (b & 0xff)) * </code></pre> * This method * is suitable for reading bytes written by - * the <code>writeChar</code> method of interface - * <code>DataOutput</code>. + * the {@code writeChar} method of interface + * {@code DataOutput}. * - * @return the <code>char</code> value read. + * @return the {@code char} value read. * @exception EOFException if this stream reaches the end before reading * all the bytes. * @exception IOException if an I/O error occurs. @@ -420,18 +420,17 @@ /** * Reads four input bytes and returns an - * <code>int</code> value. Let <code>a-d</code> + * {@code int} value. Let {@code a-d} * be the first through fourth bytes read. The value returned is: - * <p><pre> - * <code> + * <p><pre><code> * (((a & 0xff) << 24) | ((b & 0xff) << 16) | *  ((c & 0xff) << 8) | (d & 0xff)) * </code></pre> * This method is suitable - * for reading bytes written by the <code>writeInt</code> - * method of interface <code>DataOutput</code>. + * for reading bytes written by the {@code writeInt} + * method of interface {@code DataOutput}. * - * @return the <code>int</code> value read. + * @return the {@code int} value read. * @exception EOFException if this stream reaches the end before reading * all the bytes. * @exception IOException if an I/O error occurs. @@ -440,10 +439,10 @@ /** * Reads eight input bytes and returns - * a <code>long</code> value. Let <code>a-h</code> + * a {@code long} value. Let {@code a-h} * be the first through eighth bytes read. * The value returned is: - * <p><pre> <code> + * <p><pre><code> * (((long)(a & 0xff) << 56) | * ((long)(b & 0xff) << 48) | * ((long)(c & 0xff) << 40) | @@ -455,10 +454,10 @@ * </code></pre> * <p> * This method is suitable - * for reading bytes written by the <code>writeLong</code> - * method of interface <code>DataOutput</code>. + * for reading bytes written by the {@code writeLong} + * method of interface {@code DataOutput}. * - * @return the <code>long</code> value read. + * @return the {@code long} value read. * @exception EOFException if this stream reaches the end before reading * all the bytes. * @exception IOException if an I/O error occurs. @@ -467,18 +466,18 @@ /** * Reads four input bytes and returns - * a <code>float</code> value. It does this - * by first constructing an <code>int</code> + * a {@code float} value. It does this + * by first constructing an {@code int} * value in exactly the manner - * of the <code>readInt</code> - * method, then converting this <code>int</code> - * value to a <code>float</code> in - * exactly the manner of the method <code>Float.intBitsToFloat</code>. + * of the {@code readInt} + * method, then converting this {@code int} + * value to a {@code float} in + * exactly the manner of the method {@code Float.intBitsToFloat}. * This method is suitable for reading - * bytes written by the <code>writeFloat</code> - * method of interface <code>DataOutput</code>. + * bytes written by the {@code writeFloat} + * method of interface {@code DataOutput}. * - * @return the <code>float</code> value read. + * @return the {@code float} value read. * @exception EOFException if this stream reaches the end before reading * all the bytes. * @exception IOException if an I/O error occurs. @@ -487,18 +486,18 @@ /** * Reads eight input bytes and returns - * a <code>double</code> value. It does this - * by first constructing a <code>long</code> + * a {@code double} value. It does this + * by first constructing a {@code long} * value in exactly the manner - * of the <code>readlong</code> - * method, then converting this <code>long</code> - * value to a <code>double</code> in exactly - * the manner of the method <code>Double.longBitsToDouble</code>. + * of the {@code readlong} + * method, then converting this {@code long} + * value to a {@code double} in exactly + * the manner of the method {@code Double.longBitsToDouble}. * This method is suitable for reading - * bytes written by the <code>writeDouble</code> - * method of interface <code>DataOutput</code>. + * bytes written by the {@code writeDouble} + * method of interface {@code DataOutput}. * - * @return the <code>double</code> value read. + * @return the {@code double} value read. * @exception EOFException if this stream reaches the end before reading * all the bytes. * @exception IOException if an I/O error occurs. @@ -512,35 +511,35 @@ * until it encounters a line terminator or * end of * file; the characters read are then - * returned as a <code>String</code>. Note + * returned as a {@code String}. Note * that because this * method processes bytes, * it does not support input of the full Unicode * character set. * <p> * If end of file is encountered - * before even one byte can be read, then <code>null</code> + * before even one byte can be read, then {@code null} * is returned. Otherwise, each byte that is - * read is converted to type <code>char</code> - * by zero-extension. If the character <code>'\n'</code> + * read is converted to type {@code char} + * by zero-extension. If the character {@code '\n'} * is encountered, it is discarded and reading - * ceases. If the character <code>'\r'</code> + * ceases. If the character {@code '\r'} * is encountered, it is discarded and, if * the following byte converts  to the - * character <code>'\n'</code>, then that is + * character {@code '\n'}, then that is * discarded also; reading then ceases. If * end of file is encountered before either - * of the characters <code>'\n'</code> and - * <code>'\r'</code> is encountered, reading - * ceases. Once reading has ceased, a <code>String</code> + * of the characters {@code '\n'} and + * {@code '\r'} is encountered, reading + * ceases. Once reading has ceased, a {@code String} * is returned that contains all the characters * read and not discarded, taken in order. * Note that every character in this string - * will have a value less than <code>\u0100</code>, - * that is, <code>(char)256</code>. + * will have a value less than {@code \u005Cu0100}, + * that is, {@code (char)256}. * * @return the next line of text from the input stream, - * or <CODE>null</CODE> if the end of file is + * or {@code null} if the end of file is * encountered before a byte can be read. * @exception IOException if an I/O error occurs. */ @@ -550,15 +549,15 @@ * Reads in a string that has been encoded using a * <a href="#modified-utf-8">modified UTF-8</a> * format. - * The general contract of <code>readUTF</code> + * The general contract of {@code readUTF} * is that it reads a representation of a Unicode * character string encoded in modified * UTF-8 format; this string of characters - * is then returned as a <code>String</code>. + * is then returned as a {@code String}. * <p> * First, two bytes are read and used to * construct an unsigned 16-bit integer in - * exactly the manner of the <code>readUnsignedShort</code> + * exactly the manner of the {@code readUnsignedShort} * method . This integer value is called the * <i>UTF length</i> and specifies the number * of additional bytes to be read. These bytes @@ -570,58 +569,58 @@ * next group. * <p> * If the first byte of a group - * matches the bit pattern <code>0xxxxxxx</code> - * (where <code>x</code> means "may be <code>0</code> - * or <code>1</code>"), then the group consists + * matches the bit pattern {@code 0xxxxxxx} + * (where {@code x} means "may be {@code 0} + * or {@code 1}"), then the group consists * of just that byte. The byte is zero-extended * to form a character. * <p> * If the first byte - * of a group matches the bit pattern <code>110xxxxx</code>, - * then the group consists of that byte <code>a</code> - * and a second byte <code>b</code>. If there - * is no byte <code>b</code> (because byte - * <code>a</code> was the last of the bytes - * to be read), or if byte <code>b</code> does - * not match the bit pattern <code>10xxxxxx</code>, - * then a <code>UTFDataFormatException</code> + * of a group matches the bit pattern {@code 110xxxxx}, + * then the group consists of that byte {@code a} + * and a second byte {@code b}. If there + * is no byte {@code b} (because byte + * {@code a} was the last of the bytes + * to be read), or if byte {@code b} does + * not match the bit pattern {@code 10xxxxxx}, + * then a {@code UTFDataFormatException} * is thrown. Otherwise, the group is converted * to the character:<p> * <pre><code>(char)(((a& 0x1F) << 6) | (b & 0x3F)) * </code></pre> * If the first byte of a group - * matches the bit pattern <code>1110xxxx</code>, - * then the group consists of that byte <code>a</code> - * and two more bytes <code>b</code> and <code>c</code>. - * If there is no byte <code>c</code> (because - * byte <code>a</code> was one of the last + * matches the bit pattern {@code 1110xxxx}, + * then the group consists of that byte {@code a} + * and two more bytes {@code b} and {@code c}. + * If there is no byte {@code c} (because + * byte {@code a} was one of the last * two of the bytes to be read), or either - * byte <code>b</code> or byte <code>c</code> - * does not match the bit pattern <code>10xxxxxx</code>, - * then a <code>UTFDataFormatException</code> + * byte {@code b} or byte {@code c} + * does not match the bit pattern {@code 10xxxxxx}, + * then a {@code UTFDataFormatException} * is thrown. Otherwise, the group is converted * to the character:<p> * <pre><code> * (char)(((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F)) * </code></pre> * If the first byte of a group matches the - * pattern <code>1111xxxx</code> or the pattern - * <code>10xxxxxx</code>, then a <code>UTFDataFormatException</code> + * pattern {@code 1111xxxx} or the pattern + * {@code 10xxxxxx}, then a {@code UTFDataFormatException} * is thrown. * <p> * If end of file is encountered * at any time during this entire process, - * then an <code>EOFException</code> is thrown. + * then an {@code EOFException} is thrown. * <p> * After every group has been converted to * a character by this process, the characters * are gathered, in the same order in which * their corresponding groups were read from - * the input stream, to form a <code>String</code>, + * the input stream, to form a {@code String}, * which is returned. * <p> - * The <code>writeUTF</code> - * method of interface <code>DataOutput</code> + * The {@code writeUTF} + * method of interface {@code DataOutput} * may be used to write data that is suitable * for reading by this method. * @return a Unicode string.
--- a/jdk/src/share/classes/java/io/LineNumberInputStream.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/java/io/LineNumberInputStream.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -30,13 +30,13 @@ * functionality of keeping track of the current line number. * <p> * A line is a sequence of bytes ending with a carriage return - * character (<code>'\r'</code>), a newline character - * (<code>'\n'</code>), or a carriage return character followed + * character ({@code '\u005Cr'}), a newline character + * ({@code '\u005Cn'}), or a carriage return character followed * immediately by a linefeed character. In all three cases, the line * terminating character(s) are returned as a single newline character. * <p> - * The line number begins at <code>0</code>, and is incremented by - * <code>1</code> when a <code>read</code> returns a newline character. + * The line number begins at {@code 0}, and is incremented by + * {@code 1} when a {@code read} returns a newline character. * * @author Arthur van Hoff * @see java.io.LineNumberReader @@ -66,22 +66,22 @@ /** * Reads the next byte of data from this input stream. The value - * byte is returned as an <code>int</code> in the range - * <code>0</code> to <code>255</code>. If no byte is available + * byte is returned as an {@code int} in the range + * {@code 0} to {@code 255}. If no byte is available * because the end of the stream has been reached, the value - * <code>-1</code> is returned. This method blocks until input data + * {@code -1} is returned. This method blocks until input data * is available, the end of the stream is detected, or an exception * is thrown. * <p> - * The <code>read</code> method of - * <code>LineNumberInputStream</code> calls the <code>read</code> + * The {@code read} method of + * {@code LineNumberInputStream} calls the {@code read} * method of the underlying input stream. It checks for carriage * returns and newline characters in the input, and modifies the * current line number as appropriate. A carriage-return character or * a carriage return followed by a newline character are both * converted into a single newline character. * - * @return the next byte of data, or <code>-1</code> if the end of this + * @return the next byte of data, or {@code -1} if the end of this * stream is reached. * @exception IOException if an I/O error occurs. * @see java.io.FilterInputStream#in @@ -111,18 +111,18 @@ } /** - * Reads up to <code>len</code> bytes of data from this input stream + * Reads up to {@code len} bytes of data from this input stream * into an array of bytes. This method blocks until some input is available. * <p> - * The <code>read</code> method of - * <code>LineNumberInputStream</code> repeatedly calls the - * <code>read</code> method of zero arguments to fill in the byte array. + * The {@code read} method of + * {@code LineNumberInputStream} repeatedly calls the + * {@code read} method of zero arguments to fill in the byte array. * * @param b the buffer into which the data is read. * @param off the start offset of the data. * @param len the maximum number of bytes read. * @return the total number of bytes read into the buffer, or - * <code>-1</code> if there is no more data because the end of + * {@code -1} if there is no more data because the end of * this stream has been reached. * @exception IOException if an I/O error occurs. * @see java.io.LineNumberInputStream#read() @@ -160,15 +160,15 @@ } /** - * Skips over and discards <code>n</code> bytes of data from this - * input stream. The <code>skip</code> method may, for a variety of + * Skips over and discards {@code n} bytes of data from this + * input stream. The {@code skip} method may, for a variety of * reasons, end up skipping over some smaller number of bytes, - * possibly <code>0</code>. The actual number of bytes skipped is - * returned. If <code>n</code> is negative, no bytes are skipped. + * possibly {@code 0}. The actual number of bytes skipped is + * returned. If {@code n} is negative, no bytes are skipped. * <p> - * The <code>skip</code> method of <code>LineNumberInputStream</code> creates + * The {@code skip} method of {@code LineNumberInputStream} creates * a byte array and then repeatedly reads into it until - * <code>n</code> bytes have been read or the end of the stream has + * {@code n} bytes have been read or the end of the stream has * been reached. * * @param n the number of bytes to be skipped. @@ -225,12 +225,12 @@ * <p> * Note that if the underlying input stream is able to supply * <i>k</i> input characters without blocking, the - * <code>LineNumberInputStream</code> can guarantee only to provide + * {@code LineNumberInputStream} can guarantee only to provide * <i>k</i>/2 characters without blocking, because the * <i>k</i> characters from the underlying input stream might - * consist of <i>k</i>/2 pairs of <code>'\r'</code> and - * <code>'\n'</code>, which are converted to just - * <i>k</i>/2 <code>'\n'</code> characters. + * consist of <i>k</i>/2 pairs of {@code '\u005Cr'} and + * {@code '\u005Cn'}, which are converted to just + * <i>k</i>/2 {@code '\u005Cn'} characters. * * @return the number of bytes that can be read from this input stream * without blocking. @@ -243,12 +243,12 @@ /** * Marks the current position in this input stream. A subsequent - * call to the <code>reset</code> method repositions this stream at + * call to the {@code reset} method repositions this stream at * the last marked position so that subsequent reads re-read the same bytes. * <p> - * The <code>mark</code> method of - * <code>LineNumberInputStream</code> remembers the current line - * number in a private variable, and then calls the <code>mark</code> + * The {@code mark} method of + * {@code LineNumberInputStream} remembers the current line + * number in a private variable, and then calls the {@code mark} * method of the underlying input stream. * * @param readlimit the maximum limit of bytes that can be read before @@ -264,12 +264,12 @@ /** * Repositions this stream to the position at the time the - * <code>mark</code> method was last called on this input stream. + * {@code mark} method was last called on this input stream. * <p> - * The <code>reset</code> method of - * <code>LineNumberInputStream</code> resets the line number to be - * the line number at the time the <code>mark</code> method was - * called, and then calls the <code>reset</code> method of the + * The {@code reset} method of + * {@code LineNumberInputStream} resets the line number to be + * the line number at the time the {@code mark} method was + * called, and then calls the {@code reset} method of the * underlying input stream. * <p> * Stream marks are intended to be used in
--- a/jdk/src/share/classes/java/io/RandomAccessFile.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/java/io/RandomAccessFile.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -41,16 +41,16 @@ * the file pointer past the bytes written. Output operations that write * past the current end of the implied array cause the array to be * extended. The file pointer can be read by the - * <code>getFilePointer</code> method and set by the <code>seek</code> + * {@code getFilePointer} method and set by the {@code seek} * method. * <p> * It is generally true of all the reading routines in this class that * if end-of-file is reached before the desired number of bytes has been - * read, an <code>EOFException</code> (which is a kind of - * <code>IOException</code>) is thrown. If any byte cannot be read for - * any reason other than end-of-file, an <code>IOException</code> other - * than <code>EOFException</code> is thrown. In particular, an - * <code>IOException</code> may be thrown if the stream has been closed. + * read, an {@code EOFException} (which is a kind of + * {@code IOException}) is thrown. If any byte cannot be read for + * any reason other than end-of-file, an {@code IOException} other + * than {@code EOFException} is thrown. In particular, an + * {@code IOException} may be thrown if the stream has been closed. * * @author unascribed * @since JDK1.0 @@ -82,12 +82,12 @@ * href="#mode"><tt>RandomAccessFile(File,String)</tt></a> constructor. * * <p> - * If there is a security manager, its <code>checkRead</code> method - * is called with the <code>name</code> argument + * If there is a security manager, its {@code checkRead} method + * is called with the {@code name} argument * as its argument to see if read access to the file is allowed. * If the mode allows writing, the security manager's - * <code>checkWrite</code> method - * is also called with the <code>name</code> argument + * {@code checkWrite} method + * is also called with the {@code name} argument * as its argument to see if write access to the file is allowed. * * @param name the system-dependent filename @@ -103,9 +103,9 @@ * that name cannot be created, or if some other error occurs * while opening or creating the file * @exception SecurityException if a security manager exists and its - * <code>checkRead</code> method denies read access to the file + * {@code checkRead} method denies read access to the file * or the mode is "rw" and the security manager's - * <code>checkWrite</code> method denies write access to the file + * {@code checkWrite} method denies write access to the file * @see java.lang.SecurityException * @see java.lang.SecurityManager#checkRead(java.lang.String) * @see java.lang.SecurityManager#checkWrite(java.lang.String) @@ -164,10 +164,10 @@ * updates to both the file's content and its metadata to be written, which * generally requires at least one more low-level I/O operation. * - * <p> If there is a security manager, its <code>checkRead</code> method is - * called with the pathname of the <code>file</code> argument as its + * <p> If there is a security manager, its {@code checkRead} method is + * called with the pathname of the {@code file} argument as its * argument to see if read access to the file is allowed. If the mode - * allows writing, the security manager's <code>checkWrite</code> method is + * allows writing, the security manager's {@code checkWrite} method is * also called with the path argument to see if write access to the file is * allowed. * @@ -185,9 +185,9 @@ * that name cannot be created, or if some other error occurs * while opening or creating the file * @exception SecurityException if a security manager exists and its - * <code>checkRead</code> method denies read access to the file + * {@code checkRead} method denies read access to the file * or the mode is "rw" and the security manager's - * <code>checkWrite</code> method denies write access to the file + * {@code checkWrite} method denies write access to the file * @see java.lang.SecurityManager#checkRead(java.lang.String) * @see java.lang.SecurityManager#checkWrite(java.lang.String) * @see java.nio.channels.FileChannel#force(boolean) @@ -253,7 +253,7 @@ * object associated with this file. * * <p> The {@link java.nio.channels.FileChannel#position() - * </code>position<code>} of the returned channel will always be equal to + * position} of the returned channel will always be equal to * this object's file-pointer offset as returned by the {@link * #getFilePointer getFilePointer} method. Changing this object's * file-pointer offset, whether explicitly or by reading or writing bytes, @@ -277,9 +277,9 @@ /** * Opens a file and returns the file descriptor. The file is - * opened in read-write mode if the O_RDWR bit in <code>mode</code> + * opened in read-write mode if the O_RDWR bit in {@code mode} * is true, else the file is opened as read-only. - * If the <code>name</code> refers to a directory, an IOException + * If the {@code name} refers to a directory, an IOException * is thrown. * * @param name the name of the file @@ -293,15 +293,15 @@ /** * Reads a byte of data from this file. The byte is returned as an - * integer in the range 0 to 255 (<code>0x00-0x0ff</code>). This + * integer in the range 0 to 255 ({@code 0x00-0x0ff}). This * method blocks if no input is yet available. * <p> - * Although <code>RandomAccessFile</code> is not a subclass of - * <code>InputStream</code>, this method behaves in exactly the same + * Although {@code RandomAccessFile} is not a subclass of + * {@code InputStream}, this method behaves in exactly the same * way as the {@link InputStream#read()} method of - * <code>InputStream</code>. + * {@code InputStream}. * - * @return the next byte of data, or <code>-1</code> if the end of the + * @return the next byte of data, or {@code -1} if the end of the * file has been reached. * @exception IOException if an I/O error occurs. Not thrown if * end-of-file has been reached. @@ -318,59 +318,59 @@ private native int readBytes(byte b[], int off, int len) throws IOException; /** - * Reads up to <code>len</code> bytes of data from this file into an + * Reads up to {@code len} bytes of data from this file into an * array of bytes. This method blocks until at least one byte of input * is available. * <p> - * Although <code>RandomAccessFile</code> is not a subclass of - * <code>InputStream</code>, this method behaves in exactly the + * Although {@code RandomAccessFile} is not a subclass of + * {@code InputStream}, this method behaves in exactly the * same way as the {@link InputStream#read(byte[], int, int)} method of - * <code>InputStream</code>. + * {@code InputStream}. * * @param b the buffer into which the data is read. - * @param off the start offset in array <code>b</code> + * @param off the start offset in array {@code b} * at which the data is written. * @param len the maximum number of bytes read. * @return the total number of bytes read into the buffer, or - * <code>-1</code> if there is no more data because the end of + * {@code -1} if there is no more data because the end of * the file has been reached. * @exception IOException If the first byte cannot be read for any reason * other than end of file, or if the random access file has been closed, or if * some other I/O error occurs. - * @exception NullPointerException If <code>b</code> is <code>null</code>. - * @exception IndexOutOfBoundsException If <code>off</code> is negative, - * <code>len</code> is negative, or <code>len</code> is greater than - * <code>b.length - off</code> + * @exception NullPointerException If {@code b} is {@code null}. + * @exception IndexOutOfBoundsException If {@code off} is negative, + * {@code len} is negative, or {@code len} is greater than + * {@code b.length - off} */ public int read(byte b[], int off, int len) throws IOException { return readBytes(b, off, len); } /** - * Reads up to <code>b.length</code> bytes of data from this file + * Reads up to {@code b.length} bytes of data from this file * into an array of bytes. This method blocks until at least one byte * of input is available. * <p> - * Although <code>RandomAccessFile</code> is not a subclass of - * <code>InputStream</code>, this method behaves in exactly the + * Although {@code RandomAccessFile} is not a subclass of + * {@code InputStream}, this method behaves in exactly the * same way as the {@link InputStream#read(byte[])} method of - * <code>InputStream</code>. + * {@code InputStream}. * * @param b the buffer into which the data is read. * @return the total number of bytes read into the buffer, or - * <code>-1</code> if there is no more data because the end of + * {@code -1} if there is no more data because the end of * this file has been reached. * @exception IOException If the first byte cannot be read for any reason * other than end of file, or if the random access file has been closed, or if * some other I/O error occurs. - * @exception NullPointerException If <code>b</code> is <code>null</code>. + * @exception NullPointerException If {@code b} is {@code null}. */ public int read(byte b[]) throws IOException { return readBytes(b, 0, b.length); } /** - * Reads <code>b.length</code> bytes from this file into the byte + * Reads {@code b.length} bytes from this file into the byte * array, starting at the current file pointer. This method reads * repeatedly from the file until the requested number of bytes are * read. This method blocks until the requested number of bytes are @@ -386,7 +386,7 @@ } /** - * Reads exactly <code>len</code> bytes from this file into the byte + * Reads exactly {@code len} bytes from this file into the byte * array, starting at the current file pointer. This method reads * repeatedly from the file until the requested number of bytes are * read. This method blocks until the requested number of bytes are @@ -410,15 +410,15 @@ } /** - * Attempts to skip over <code>n</code> bytes of input discarding the + * Attempts to skip over {@code n} bytes of input discarding the * skipped bytes. * <p> * * This method may skip over some smaller number of bytes, possibly zero. * This may result from any of a number of conditions; reaching end of - * file before <code>n</code> bytes have been skipped is only one - * possibility. This method never throws an <code>EOFException</code>. - * The actual number of bytes skipped is returned. If <code>n</code> + * file before {@code n} bytes have been skipped is only one + * possibility. This method never throws an {@code EOFException}. + * The actual number of bytes skipped is returned. If {@code n} * is negative, no bytes are skipped. * * @param n the number of bytes to be skipped. @@ -451,7 +451,7 @@ * Writes the specified byte to this file. The write starts at * the current file pointer. * - * @param b the <code>byte</code> to be written. + * @param b the {@code byte} to be written. * @exception IOException if an I/O error occurs. */ public native void write(int b) throws IOException; @@ -467,7 +467,7 @@ private native void writeBytes(byte b[], int off, int len) throws IOException; /** - * Writes <code>b.length</code> bytes from the specified byte array + * Writes {@code b.length} bytes from the specified byte array * to this file, starting at the current file pointer. * * @param b the data. @@ -478,8 +478,8 @@ } /** - * Writes <code>len</code> bytes from the specified byte array - * starting at offset <code>off</code> to this file. + * Writes {@code len} bytes from the specified byte array + * starting at offset {@code off} to this file. * * @param b the data. * @param off the start offset in the data. @@ -512,8 +512,8 @@ * @param pos the offset position, measured in bytes from the * beginning of the file, at which to set the file * pointer. - * @exception IOException if <code>pos</code> is less than - * <code>0</code> or if an I/O error occurs. + * @exception IOException if {@code pos} is less than + * {@code 0} or if an I/O error occurs. */ public native void seek(long pos) throws IOException; @@ -529,14 +529,14 @@ * Sets the length of this file. * * <p> If the present length of the file as returned by the - * <code>length</code> method is greater than the <code>newLength</code> + * {@code length} method is greater than the {@code newLength} * argument then the file will be truncated. In this case, if the file - * offset as returned by the <code>getFilePointer</code> method is greater - * than <code>newLength</code> then after this method returns the offset - * will be equal to <code>newLength</code>. + * offset as returned by the {@code getFilePointer} method is greater + * than {@code newLength} then after this method returns the offset + * will be equal to {@code newLength}. * * <p> If the present length of the file as returned by the - * <code>length</code> method is smaller than the <code>newLength</code> + * {@code length} method is smaller than the {@code newLength} * argument then the file will be extended. In this case, the contents of * the extended portion of the file are not defined. * @@ -584,14 +584,14 @@ // /** - * Reads a <code>boolean</code> from this file. This method reads a + * Reads a {@code boolean} from this file. This method reads a * single byte from the file, starting at the current file pointer. - * A value of <code>0</code> represents - * <code>false</code>. Any other value represents <code>true</code>. + * A value of {@code 0} represents + * {@code false}. Any other value represents {@code true}. * This method blocks until the byte is read, the end of the stream * is detected, or an exception is thrown. * - * @return the <code>boolean</code> value read. + * @return the {@code boolean} value read. * @exception EOFException if this file has reached the end. * @exception IOException if an I/O error occurs. */ @@ -605,7 +605,7 @@ /** * Reads a signed eight-bit value from this file. This method reads a * byte from the file, starting from the current file pointer. - * If the byte read is <code>b</code>, where + * If the byte read is {@code b}, where * <code>0 <= b <= 255</code>, * then the result is: * <blockquote><pre> @@ -616,7 +616,7 @@ * is detected, or an exception is thrown. * * @return the next byte of this file as a signed eight-bit - * <code>byte</code>. + * {@code byte}. * @exception EOFException if this file has reached the end. * @exception IOException if an I/O error occurs. */ @@ -651,8 +651,8 @@ * Reads a signed 16-bit number from this file. The method reads two * bytes from this file, starting at the current file pointer. * If the two bytes read, in order, are - * <code>b1</code> and <code>b2</code>, where each of the two values is - * between <code>0</code> and <code>255</code>, inclusive, then the + * {@code b1} and {@code b2}, where each of the two values is + * between {@code 0} and {@code 255}, inclusive, then the * result is equal to: * <blockquote><pre> * (short)((b1 << 8) | b2) @@ -679,7 +679,7 @@ * Reads an unsigned 16-bit number from this file. This method reads * two bytes from the file, starting at the current file pointer. * If the bytes read, in order, are - * <code>b1</code> and <code>b2</code>, where + * {@code b1} and {@code b2}, where * <code>0 <= b1, b2 <= 255</code>, * then the result is equal to: * <blockquote><pre> @@ -707,7 +707,7 @@ * Reads a character from this file. This method reads two * bytes from the file, starting at the current file pointer. * If the bytes read, in order, are - * <code>b1</code> and <code>b2</code>, where + * {@code b1} and {@code b2}, where * <code>0 <= b1, b2 <= 255</code>, * then the result is equal to: * <blockquote><pre> @@ -718,7 +718,7 @@ * stream is detected, or an exception is thrown. * * @return the next two bytes of this file, interpreted as a - * <code>char</code>. + * {@code char}. * @exception EOFException if this file reaches the end before reading * two bytes. * @exception IOException if an I/O error occurs. @@ -734,8 +734,8 @@ /** * Reads a signed 32-bit integer from this file. This method reads 4 * bytes from the file, starting at the current file pointer. - * If the bytes read, in order, are <code>b1</code>, - * <code>b2</code>, <code>b3</code>, and <code>b4</code>, where + * If the bytes read, in order, are {@code b1}, + * {@code b2}, {@code b3}, and {@code b4}, where * <code>0 <= b1, b2, b3, b4 <= 255</code>, * then the result is equal to: * <blockquote><pre> @@ -746,7 +746,7 @@ * stream is detected, or an exception is thrown. * * @return the next four bytes of this file, interpreted as an - * <code>int</code>. + * {@code int}. * @exception EOFException if this file reaches the end before reading * four bytes. * @exception IOException if an I/O error occurs. @@ -765,9 +765,9 @@ * Reads a signed 64-bit integer from this file. This method reads eight * bytes from the file, starting at the current file pointer. * If the bytes read, in order, are - * <code>b1</code>, <code>b2</code>, <code>b3</code>, - * <code>b4</code>, <code>b5</code>, <code>b6</code>, - * <code>b7</code>, and <code>b8,</code> where: + * {@code b1}, {@code b2}, {@code b3}, + * {@code b4}, {@code b5}, {@code b6}, + * {@code b7}, and {@code b8,} where: * <blockquote><pre> * 0 <= b1, b2, b3, b4, b5, b6, b7, b8 <=255, * </pre></blockquote> @@ -784,7 +784,7 @@ * stream is detected, or an exception is thrown. * * @return the next eight bytes of this file, interpreted as a - * <code>long</code>. + * {@code long}. * @exception EOFException if this file reaches the end before reading * eight bytes. * @exception IOException if an I/O error occurs. @@ -794,18 +794,18 @@ } /** - * Reads a <code>float</code> from this file. This method reads an - * <code>int</code> value, starting at the current file pointer, - * as if by the <code>readInt</code> method - * and then converts that <code>int</code> to a <code>float</code> - * using the <code>intBitsToFloat</code> method in class - * <code>Float</code>. + * Reads a {@code float} from this file. This method reads an + * {@code int} value, starting at the current file pointer, + * as if by the {@code readInt} method + * and then converts that {@code int} to a {@code float} + * using the {@code intBitsToFloat} method in class + * {@code Float}. * <p> * This method blocks until the four bytes are read, the end of the * stream is detected, or an exception is thrown. * * @return the next four bytes of this file, interpreted as a - * <code>float</code>. + * {@code float}. * @exception EOFException if this file reaches the end before reading * four bytes. * @exception IOException if an I/O error occurs. @@ -817,18 +817,18 @@ } /** - * Reads a <code>double</code> from this file. This method reads a - * <code>long</code> value, starting at the current file pointer, - * as if by the <code>readLong</code> method - * and then converts that <code>long</code> to a <code>double</code> - * using the <code>longBitsToDouble</code> method in - * class <code>Double</code>. + * Reads a {@code double} from this file. This method reads a + * {@code long} value, starting at the current file pointer, + * as if by the {@code readLong} method + * and then converts that {@code long} to a {@code double} + * using the {@code longBitsToDouble} method in + * class {@code Double}. * <p> * This method blocks until the eight bytes are read, the end of the * stream is detected, or an exception is thrown. * * @return the next eight bytes of this file, interpreted as a - * <code>double</code>. + * {@code double}. * @exception EOFException if this file reaches the end before reading * eight bytes. * @exception IOException if an I/O error occurs. @@ -849,7 +849,7 @@ * therefore, support the full Unicode character set. * * <p> A line of text is terminated by a carriage-return character - * (<code>'\r'</code>), a newline character (<code>'\n'</code>), a + * ({@code '\u005Cr'}), a newline character ({@code '\u005Cn'}), a * carriage-return character immediately followed by a newline character, * or the end of the file. Line-terminating characters are discarded and * are not included as part of the string returned. @@ -901,7 +901,7 @@ * <p> * The first two bytes are read, starting from the current file * pointer, as if by - * <code>readUnsignedShort</code>. This value gives the number of + * {@code readUnsignedShort}. This value gives the number of * following bytes that are in the encoded string, not * the length of the resulting string. The following bytes are then * interpreted as bytes encoding characters in the modified UTF-8 format @@ -923,13 +923,13 @@ } /** - * Writes a <code>boolean</code> to the file as a one-byte value. The - * value <code>true</code> is written out as the value - * <code>(byte)1</code>; the value <code>false</code> is written out - * as the value <code>(byte)0</code>. The write starts at + * Writes a {@code boolean} to the file as a one-byte value. The + * value {@code true} is written out as the value + * {@code (byte)1}; the value {@code false} is written out + * as the value {@code (byte)0}. The write starts at * the current position of the file pointer. * - * @param v a <code>boolean</code> value to be written. + * @param v a {@code boolean} value to be written. * @exception IOException if an I/O error occurs. */ public final void writeBoolean(boolean v) throws IOException { @@ -938,10 +938,10 @@ } /** - * Writes a <code>byte</code> to the file as a one-byte value. The + * Writes a {@code byte} to the file as a one-byte value. The * write starts at the current position of the file pointer. * - * @param v a <code>byte</code> value to be written. + * @param v a {@code byte} value to be written. * @exception IOException if an I/O error occurs. */ public final void writeByte(int v) throws IOException { @@ -950,10 +950,10 @@ } /** - * Writes a <code>short</code> to the file as two bytes, high byte first. + * Writes a {@code short} to the file as two bytes, high byte first. * The write starts at the current position of the file pointer. * - * @param v a <code>short</code> to be written. + * @param v a {@code short} to be written. * @exception IOException if an I/O error occurs. */ public final void writeShort(int v) throws IOException { @@ -963,11 +963,11 @@ } /** - * Writes a <code>char</code> to the file as a two-byte value, high + * Writes a {@code char} to the file as a two-byte value, high * byte first. The write starts at the current position of the * file pointer. * - * @param v a <code>char</code> value to be written. + * @param v a {@code char} value to be written. * @exception IOException if an I/O error occurs. */ public final void writeChar(int v) throws IOException { @@ -977,10 +977,10 @@ } /** - * Writes an <code>int</code> to the file as four bytes, high byte first. + * Writes an {@code int} to the file as four bytes, high byte first. * The write starts at the current position of the file pointer. * - * @param v an <code>int</code> to be written. + * @param v an {@code int} to be written. * @exception IOException if an I/O error occurs. */ public final void writeInt(int v) throws IOException { @@ -992,10 +992,10 @@ } /** - * Writes a <code>long</code> to the file as eight bytes, high byte first. + * Writes a {@code long} to the file as eight bytes, high byte first. * The write starts at the current position of the file pointer. * - * @param v a <code>long</code> to be written. + * @param v a {@code long} to be written. * @exception IOException if an I/O error occurs. */ public final void writeLong(long v) throws IOException { @@ -1011,13 +1011,13 @@ } /** - * Converts the float argument to an <code>int</code> using the - * <code>floatToIntBits</code> method in class <code>Float</code>, - * and then writes that <code>int</code> value to the file as a + * Converts the float argument to an {@code int} using the + * {@code floatToIntBits} method in class {@code Float}, + * and then writes that {@code int} value to the file as a * four-byte quantity, high byte first. The write starts at the * current position of the file pointer. * - * @param v a <code>float</code> value to be written. + * @param v a {@code float} value to be written. * @exception IOException if an I/O error occurs. * @see java.lang.Float#floatToIntBits(float) */ @@ -1026,13 +1026,13 @@ } /** - * Converts the double argument to a <code>long</code> using the - * <code>doubleToLongBits</code> method in class <code>Double</code>, - * and then writes that <code>long</code> value to the file as an + * Converts the double argument to a {@code long} using the + * {@code doubleToLongBits} method in class {@code Double}, + * and then writes that {@code long} value to the file as an * eight-byte quantity, high byte first. The write starts at the current * position of the file pointer. * - * @param v a <code>double</code> value to be written. + * @param v a {@code double} value to be written. * @exception IOException if an I/O error occurs. * @see java.lang.Double#doubleToLongBits(double) */ @@ -1060,10 +1060,10 @@ /** * Writes a string to the file as a sequence of characters. Each * character is written to the data output stream as if by the - * <code>writeChar</code> method. The write starts at the current + * {@code writeChar} method. The write starts at the current * position of the file pointer. * - * @param s a <code>String</code> value to be written. + * @param s a {@code String} value to be written. * @exception IOException if an I/O error occurs. * @see java.io.RandomAccessFile#writeChar(int) */ @@ -1087,7 +1087,7 @@ * <p> * First, two bytes are written to the file, starting at the * current file pointer, as if by the - * <code>writeShort</code> method giving the number of bytes to + * {@code writeShort} method giving the number of bytes to * follow. This value is the number of bytes actually written out, * not the length of the string. Following the length, each character * of the string is output, in sequence, using the modified UTF-8 encoding
--- a/jdk/src/share/classes/java/io/StreamTokenizer.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/java/io/StreamTokenizer.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 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 @@ -28,7 +28,7 @@ import java.util.Arrays; /** - * The <code>StreamTokenizer</code> class takes an input stream and + * The {@code StreamTokenizer} class takes an input stream and * parses it into "tokens", allowing the tokens to be * read one at a time. The parsing process is controlled by a table * and a number of flags that can be set to various states. The @@ -36,7 +36,7 @@ * strings, and various comment styles. * <p> * Each byte read from the input stream is regarded as a character - * in the range <code>'\u0000'</code> through <code>'\u00FF'</code>. + * in the range {@code '\u005Cu0000'} through {@code '\u005Cu00FF'}. * The character value is used to look up five possible attributes of * the character: <i>white space</i>, <i>alphabetic</i>, * <i>numeric</i>, <i>string quote</i>, and <i>comment character</i>. @@ -53,8 +53,8 @@ * <p> * A typical application first constructs an instance of this class, * sets up the syntax tables, and then repeatedly loops calling the - * <code>nextToken</code> method in each iteration of the loop until - * it returns the value <code>TT_EOF</code>. + * {@code nextToken} method in each iteration of the loop until + * it returns the value {@code TT_EOF}. * * @author James Gosling * @see java.io.StreamTokenizer#nextToken() @@ -99,19 +99,19 @@ private static final byte CT_COMMENT = 16; /** - * After a call to the <code>nextToken</code> method, this field + * After a call to the {@code nextToken} method, this field * contains the type of the token just read. For a single character * token, its value is the single character, converted to an integer. * For a quoted string token, its value is the quote character. * Otherwise, its value is one of the following: * <ul> - * <li><code>TT_WORD</code> indicates that the token is a word. - * <li><code>TT_NUMBER</code> indicates that the token is a number. - * <li><code>TT_EOL</code> indicates that the end of line has been read. + * <li>{@code TT_WORD} indicates that the token is a word. + * <li>{@code TT_NUMBER} indicates that the token is a number. + * <li>{@code TT_EOL} indicates that the end of line has been read. * The field can only have this value if the - * <code>eolIsSignificant</code> method has been called with the - * argument <code>true</code>. - * <li><code>TT_EOF</code> indicates that the end of the input stream + * {@code eolIsSignificant} method has been called with the + * argument {@code true}. + * <li>{@code TT_EOF} indicates that the end of the input stream * has been reached. * </ul> * <p> @@ -160,8 +160,8 @@ * the string. * <p> * The current token is a word when the value of the - * <code>ttype</code> field is <code>TT_WORD</code>. The current token is - * a quoted string token when the value of the <code>ttype</code> field is + * {@code ttype} field is {@code TT_WORD}. The current token is + * a quoted string token when the value of the {@code ttype} field is * a quote character. * <p> * The initial value of this field is null. @@ -175,7 +175,7 @@ /** * If the current token is a number, this field contains the value * of that number. The current token is a number when the value of - * the <code>ttype</code> field is <code>TT_NUMBER</code>. + * the {@code ttype} field is {@code TT_NUMBER}. * <p> * The initial value of this field is 0.0. * @@ -201,14 +201,14 @@ * stream. The stream tokenizer is initialized to the following * default state: * <ul> - * <li>All byte values <code>'A'</code> through <code>'Z'</code>, - * <code>'a'</code> through <code>'z'</code>, and - * <code>'\u00A0'</code> through <code>'\u00FF'</code> are + * <li>All byte values {@code 'A'} through {@code 'Z'}, + * {@code 'a'} through {@code 'z'}, and + * {@code '\u005Cu00A0'} through {@code '\u005Cu00FF'} are * considered to be alphabetic. - * <li>All byte values <code>'\u0000'</code> through - * <code>'\u0020'</code> are considered to be white space. - * <li><code>'/'</code> is a comment character. - * <li>Single quote <code>'\''</code> and double quote <code>'"'</code> + * <li>All byte values {@code '\u005Cu0000'} through + * {@code '\u005Cu0020'} are considered to be white space. + * <li>{@code '/'} is a comment character. + * <li>Single quote {@code '\u005C''} and double quote {@code '"'} * are string quote characters. * <li>Numbers are parsed. * <li>Ends of lines are treated as white space, not as separate tokens. @@ -252,7 +252,7 @@ /** * Resets this tokenizer's syntax table so that all characters are - * "ordinary." See the <code>ordinaryChar</code> method + * "ordinary." See the {@code ordinaryChar} method * for more information on a character being ordinary. * * @see java.io.StreamTokenizer#ordinaryChar(int) @@ -305,7 +305,7 @@ * Specifies that all characters <i>c</i> in the range * <code>low <= <i>c</i> <= high</code> * are "ordinary" in this tokenizer. See the - * <code>ordinaryChar</code> method for more information on a + * {@code ordinaryChar} method for more information on a * character being ordinary. * * @param low the low end of the range. @@ -327,12 +327,12 @@ * character has as a comment character, word component, string * delimiter, white space, or number character. When such a character * is encountered by the parser, the parser treats it as a - * single-character token and sets <code>ttype</code> field to the + * single-character token and sets {@code ttype} field to the * character value. * * <p>Making a line terminator character "ordinary" may interfere - * with the ability of a <code>StreamTokenizer</code> to count - * lines. The <code>lineno</code> method may no longer reflect + * with the ability of a {@code StreamTokenizer} to count + * lines. The {@code lineno} method may no longer reflect * the presence of such terminator characters in its line count. * * @param ch the character. @@ -361,9 +361,9 @@ * Specifies that matching pairs of this character delimit string * constants in this tokenizer. * <p> - * When the <code>nextToken</code> method encounters a string - * constant, the <code>ttype</code> field is set to the string - * delimiter and the <code>sval</code> field is set to the body of + * When the {@code nextToken} method encounters a string + * constant, the {@code ttype} field is set to the string + * delimiter and the {@code sval} field is set to the body of * the string. * <p> * If a string quote character is encountered, then a string is @@ -371,7 +371,7 @@ * the string quote character, up to (but not including) the next * occurrence of that same string quote character, or a line * terminator, or end of file. The usual escape sequences such as - * <code>"\n"</code> and <code>"\t"</code> are recognized and + * {@code "\u005Cn"} and {@code "\u005Ct"} are recognized and * converted to single characters as the string is parsed. * * <p>Any other attribute settings for the specified character are cleared. @@ -398,9 +398,9 @@ * <p> * When the parser encounters a word token that has the format of a * double precision floating-point number, it treats the token as a - * number rather than a word, by setting the <code>ttype</code> - * field to the value <code>TT_NUMBER</code> and putting the numeric - * value of the token into the <code>nval</code> field. + * number rather than a word, by setting the {@code ttype} + * field to the value {@code TT_NUMBER} and putting the numeric + * value of the token into the {@code nval} field. * * @see java.io.StreamTokenizer#nval * @see java.io.StreamTokenizer#TT_NUMBER @@ -416,21 +416,21 @@ /** * Determines whether or not ends of line are treated as tokens. * If the flag argument is true, this tokenizer treats end of lines - * as tokens; the <code>nextToken</code> method returns - * <code>TT_EOL</code> and also sets the <code>ttype</code> field to + * as tokens; the {@code nextToken} method returns + * {@code TT_EOL} and also sets the {@code ttype} field to * this value when an end of line is read. * <p> * A line is a sequence of characters ending with either a - * carriage-return character (<code>'\r'</code>) or a newline - * character (<code>'\n'</code>). In addition, a carriage-return + * carriage-return character ({@code '\u005Cr'}) or a newline + * character ({@code '\u005Cn'}). In addition, a carriage-return * character followed immediately by a newline character is treated * as a single end-of-line token. * <p> - * If the <code>flag</code> is false, end-of-line characters are + * If the {@code flag} is false, end-of-line characters are * treated as white space and serve only to separate tokens. * - * @param flag <code>true</code> indicates that end-of-line characters - * are separate tokens; <code>false</code> indicates that + * @param flag {@code true} indicates that end-of-line characters + * are separate tokens; {@code false} indicates that * end-of-line characters are white space. * @see java.io.StreamTokenizer#nextToken() * @see java.io.StreamTokenizer#ttype @@ -442,14 +442,14 @@ /** * Determines whether or not the tokenizer recognizes C-style comments. - * If the flag argument is <code>true</code>, this stream tokenizer + * If the flag argument is {@code true}, this stream tokenizer * recognizes C-style comments. All text between successive - * occurrences of <code>/*</code> and <code>*/</code> are discarded. + * occurrences of {@code /*} and <code>*/</code> are discarded. * <p> - * If the flag argument is <code>false</code>, then C-style comments + * If the flag argument is {@code false}, then C-style comments * are not treated specially. * - * @param flag <code>true</code> indicates to recognize and ignore + * @param flag {@code true} indicates to recognize and ignore * C-style comments. */ public void slashStarComments(boolean flag) { @@ -458,15 +458,15 @@ /** * Determines whether or not the tokenizer recognizes C++-style comments. - * If the flag argument is <code>true</code>, this stream tokenizer + * If the flag argument is {@code true}, this stream tokenizer * recognizes C++-style comments. Any occurrence of two consecutive - * slash characters (<code>'/'</code>) is treated as the beginning of + * slash characters ({@code '/'}) is treated as the beginning of * a comment that extends to the end of the line. * <p> - * If the flag argument is <code>false</code>, then C++-style + * If the flag argument is {@code false}, then C++-style * comments are not treated specially. * - * @param flag <code>true</code> indicates to recognize and ignore + * @param flag {@code true} indicates to recognize and ignore * C++-style comments. */ public void slashSlashComments(boolean flag) { @@ -475,16 +475,16 @@ /** * Determines whether or not word token are automatically lowercased. - * If the flag argument is <code>true</code>, then the value in the - * <code>sval</code> field is lowercased whenever a word token is - * returned (the <code>ttype</code> field has the - * value <code>TT_WORD</code> by the <code>nextToken</code> method + * If the flag argument is {@code true}, then the value in the + * {@code sval} field is lowercased whenever a word token is + * returned (the {@code ttype} field has the + * value {@code TT_WORD} by the {@code nextToken} method * of this tokenizer. * <p> - * If the flag argument is <code>false</code>, then the - * <code>sval</code> field is not modified. + * If the flag argument is {@code false}, then the + * {@code sval} field is not modified. * - * @param fl <code>true</code> indicates that all word tokens should + * @param fl {@code true} indicates that all word tokens should * be lowercased. * @see java.io.StreamTokenizer#nextToken() * @see java.io.StreamTokenizer#ttype @@ -506,9 +506,9 @@ /** * Parses the next token from the input stream of this tokenizer. - * The type of the next token is returned in the <code>ttype</code> + * The type of the next token is returned in the {@code ttype} * field. Additional information about the token may be in the - * <code>nval</code> field or the <code>sval</code> field of this + * {@code nval} field or the {@code sval} field of this * tokenizer. * <p> * Typical clients of this @@ -516,7 +516,7 @@ * calling nextToken to parse successive tokens until TT_EOF * is returned. * - * @return the value of the <code>ttype</code> field. + * @return the value of the {@code ttype} field. * @exception IOException if an I/O error occurs. * @see java.io.StreamTokenizer#nval * @see java.io.StreamTokenizer#sval @@ -752,10 +752,10 @@ } /** - * Causes the next call to the <code>nextToken</code> method of this - * tokenizer to return the current value in the <code>ttype</code> - * field, and not to modify the value in the <code>nval</code> or - * <code>sval</code> field. + * Causes the next call to the {@code nextToken} method of this + * tokenizer to return the current value in the {@code ttype} + * field, and not to modify the value in the {@code nval} or + * {@code sval} field. * * @see java.io.StreamTokenizer#nextToken() * @see java.io.StreamTokenizer#nval
--- a/jdk/src/share/classes/java/lang/AbstractStringBuilder.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -91,10 +91,10 @@ * array is allocated with greater capacity. The new capacity is the * larger of: * <ul> - * <li>The <code>minimumCapacity</code> argument. - * <li>Twice the old capacity, plus <code>2</code>. + * <li>The {@code minimumCapacity} argument. + * <li>Twice the old capacity, plus {@code 2}. * </ul> - * If the <code>minimumCapacity</code> argument is nonpositive, this + * If the {@code minimumCapacity} argument is nonpositive, this * method takes no action and simply returns. * * @param minimumCapacity the minimum desired capacity. @@ -147,26 +147,26 @@ * Sets the length of the character sequence. * The sequence is changed to a new character sequence * whose length is specified by the argument. For every nonnegative - * index <i>k</i> less than <code>newLength</code>, the character at + * index <i>k</i> less than {@code newLength}, the character at * index <i>k</i> in the new character sequence is the same as the * character at index <i>k</i> in the old sequence if <i>k</i> is less * than the length of the old character sequence; otherwise, it is the - * null character <code>'\u0000'</code>. + * null character {@code '\u005Cu0000'}. * - * In other words, if the <code>newLength</code> argument is less than + * In other words, if the {@code newLength} argument is less than * the current length, the length is changed to the specified length. * <p> - * If the <code>newLength</code> argument is greater than or equal + * If the {@code newLength} argument is greater than or equal * to the current length, sufficient null characters - * (<code>'\u0000'</code>) are appended so that - * length becomes the <code>newLength</code> argument. + * ({@code '\u005Cu0000'}) are appended so that + * length becomes the {@code newLength} argument. * <p> - * The <code>newLength</code> argument must be greater than or equal - * to <code>0</code>. + * The {@code newLength} argument must be greater than or equal + * to {@code 0}. * * @param newLength the new length * @throws IndexOutOfBoundsException if the - * <code>newLength</code> argument is negative. + * {@code newLength} argument is negative. */ public void setLength(int newLength) { if (newLength < 0) @@ -182,21 +182,21 @@ } /** - * Returns the <code>char</code> value in this sequence at the specified index. - * The first <code>char</code> value is at index <code>0</code>, the next at index - * <code>1</code>, and so on, as in array indexing. + * Returns the {@code char} value in this sequence at the specified index. + * The first {@code char} value is at index {@code 0}, the next at index + * {@code 1}, and so on, as in array indexing. * <p> * The index argument must be greater than or equal to - * <code>0</code>, and less than the length of this sequence. + * {@code 0}, and less than the length of this sequence. * - * <p>If the <code>char</code> value specified by the index is a + * <p>If the {@code char} value specified by the index is a * <a href="Character.html#unicode">surrogate</a>, the surrogate * value is returned. * - * @param index the index of the desired <code>char</code> value. - * @return the <code>char</code> value at the specified index. - * @throws IndexOutOfBoundsException if <code>index</code> is - * negative or greater than or equal to <code>length()</code>. + * @param index the index of the desired {@code char} value. + * @return the {@code char} value at the specified index. + * @throws IndexOutOfBoundsException if {@code index} is + * negative or greater than or equal to {@code length()}. */ public char charAt(int index) { if ((index < 0) || (index >= count)) @@ -206,22 +206,22 @@ /** * Returns the character (Unicode code point) at the specified - * index. The index refers to <code>char</code> values - * (Unicode code units) and ranges from <code>0</code> to - * {@link #length()}<code> - 1</code>. + * index. The index refers to {@code char} values + * (Unicode code units) and ranges from {@code 0} to + * {@link #length()}{@code - 1}. * - * <p> If the <code>char</code> value specified at the given index + * <p> If the {@code char} value specified at the given index * is in the high-surrogate range, the following index is less * than the length of this sequence, and the - * <code>char</code> value at the following index is in the + * {@code char} value at the following index is in the * low-surrogate range, then the supplementary code point * corresponding to this surrogate pair is returned. Otherwise, - * the <code>char</code> value at the given index is returned. + * the {@code char} value at the given index is returned. * - * @param index the index to the <code>char</code> values + * @param index the index to the {@code char} values * @return the code point value of the character at the - * <code>index</code> - * @exception IndexOutOfBoundsException if the <code>index</code> + * {@code index} + * @exception IndexOutOfBoundsException if the {@code index} * argument is negative or not less than the length of this * sequence. */ @@ -234,22 +234,22 @@ /** * Returns the character (Unicode code point) before the specified - * index. The index refers to <code>char</code> values - * (Unicode code units) and ranges from <code>1</code> to {@link + * index. The index refers to {@code char} values + * (Unicode code units) and ranges from {@code 1} to {@link * #length()}. * - * <p> If the <code>char</code> value at <code>(index - 1)</code> - * is in the low-surrogate range, <code>(index - 2)</code> is not - * negative, and the <code>char</code> value at <code>(index - - * 2)</code> is in the high-surrogate range, then the + * <p> If the {@code char} value at {@code (index - 1)} + * is in the low-surrogate range, {@code (index - 2)} is not + * negative, and the {@code char} value at {@code (index - + * 2)} is in the high-surrogate range, then the * supplementary code point value of the surrogate pair is - * returned. If the <code>char</code> value at <code>index - - * 1</code> is an unpaired low-surrogate or a high-surrogate, the + * returned. If the {@code char} value at {@code index - + * 1} is an unpaired low-surrogate or a high-surrogate, the * surrogate value is returned. * * @param index the index following the code point that should be returned * @return the Unicode code point value before the given index. - * @exception IndexOutOfBoundsException if the <code>index</code> + * @exception IndexOutOfBoundsException if the {@code index} * argument is less than 1 or greater than the length * of this sequence. */ @@ -264,22 +264,22 @@ /** * Returns the number of Unicode code points in the specified text * range of this sequence. The text range begins at the specified - * <code>beginIndex</code> and extends to the <code>char</code> at - * index <code>endIndex - 1</code>. Thus the length (in - * <code>char</code>s) of the text range is - * <code>endIndex-beginIndex</code>. Unpaired surrogates within + * {@code beginIndex} and extends to the {@code char} at + * index {@code endIndex - 1}. Thus the length (in + * {@code char}s) of the text range is + * {@code endIndex-beginIndex}. Unpaired surrogates within * this sequence count as one code point each. * - * @param beginIndex the index to the first <code>char</code> of + * @param beginIndex the index to the first {@code char} of * the text range. - * @param endIndex the index after the last <code>char</code> of + * @param endIndex the index after the last {@code char} of * the text range. * @return the number of Unicode code points in the specified text * range * @exception IndexOutOfBoundsException if the - * <code>beginIndex</code> is negative, or <code>endIndex</code> + * {@code beginIndex} is negative, or {@code endIndex} * is larger than the length of this sequence, or - * <code>beginIndex</code> is larger than <code>endIndex</code>. + * {@code beginIndex} is larger than {@code endIndex}. */ public int codePointCount(int beginIndex, int endIndex) { if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) { @@ -290,22 +290,22 @@ /** * Returns the index within this sequence that is offset from the - * given <code>index</code> by <code>codePointOffset</code> code + * given {@code index} by {@code codePointOffset} code * points. Unpaired surrogates within the text range given by - * <code>index</code> and <code>codePointOffset</code> count as + * {@code index} and {@code codePointOffset} count as * one code point each. * * @param index the index to be offset * @param codePointOffset the offset in code points * @return the index within this sequence - * @exception IndexOutOfBoundsException if <code>index</code> + * @exception IndexOutOfBoundsException if {@code index} * is negative or larger then the length of this sequence, - * or if <code>codePointOffset</code> is positive and the subsequence - * starting with <code>index</code> has fewer than - * <code>codePointOffset</code> code points, - * or if <code>codePointOffset</code> is negative and the subsequence - * before <code>index</code> has fewer than the absolute value of - * <code>codePointOffset</code> code points. + * or if {@code codePointOffset} is positive and the subsequence + * starting with {@code index} has fewer than + * {@code codePointOffset} code points, + * or if {@code codePointOffset} is negative and the subsequence + * before {@code index} has fewer than the absolute value of + * {@code codePointOffset} code points. */ public int offsetByCodePoints(int index, int codePointOffset) { if (index < 0 || index > count) { @@ -317,12 +317,12 @@ /** * Characters are copied from this sequence into the - * destination character array <code>dst</code>. The first character to - * be copied is at index <code>srcBegin</code>; the last character to - * be copied is at index <code>srcEnd-1</code>. The total number of - * characters to be copied is <code>srcEnd-srcBegin</code>. The - * characters are copied into the subarray of <code>dst</code> starting - * at index <code>dstBegin</code> and ending at index: + * destination character array {@code dst}. The first character to + * be copied is at index {@code srcBegin}; the last character to + * be copied is at index {@code srcEnd-1}. The total number of + * characters to be copied is {@code srcEnd-srcBegin}. The + * characters are copied into the subarray of {@code dst} starting + * at index {@code dstBegin} and ending at index: * <p><blockquote><pre> * dstbegin + (srcEnd-srcBegin) - 1 * </pre></blockquote> @@ -330,19 +330,19 @@ * @param srcBegin start copying at this offset. * @param srcEnd stop copying at this offset. * @param dst the array to copy the data into. - * @param dstBegin offset into <code>dst</code>. - * @throws NullPointerException if <code>dst</code> is - * <code>null</code>. + * @param dstBegin offset into {@code dst}. + * @throws NullPointerException if {@code dst} is + * {@code null}. * @throws IndexOutOfBoundsException if any of the following is true: * <ul> - * <li><code>srcBegin</code> is negative - * <li><code>dstBegin</code> is negative - * <li>the <code>srcBegin</code> argument is greater than - * the <code>srcEnd</code> argument. - * <li><code>srcEnd</code> is greater than - * <code>this.length()</code>. - * <li><code>dstBegin+srcEnd-srcBegin</code> is greater than - * <code>dst.length</code> + * <li>{@code srcBegin} is negative + * <li>{@code dstBegin} is negative + * <li>the {@code srcBegin} argument is greater than + * the {@code srcEnd} argument. + * <li>{@code srcEnd} is greater than + * {@code this.length()}. + * <li>{@code dstBegin+srcEnd-srcBegin} is greater than + * {@code dst.length} * </ul> */ public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) @@ -357,18 +357,18 @@ } /** - * The character at the specified index is set to <code>ch</code>. This + * The character at the specified index is set to {@code ch}. This * sequence is altered to represent a new character sequence that is * identical to the old character sequence, except that it contains the - * character <code>ch</code> at position <code>index</code>. + * character {@code ch} at position {@code index}. * <p> * The index argument must be greater than or equal to - * <code>0</code>, and less than the length of this sequence. + * {@code 0}, and less than the length of this sequence. * * @param index the index of the character to modify. * @param ch the new character. - * @throws IndexOutOfBoundsException if <code>index</code> is - * negative or greater than or equal to <code>length()</code>. + * @throws IndexOutOfBoundsException if {@code index} is + * negative or greater than or equal to {@code length()}. */ public void setCharAt(int index, char ch) { if ((index < 0) || (index >= count)) @@ -741,21 +741,21 @@ } /** - * Removes the <code>char</code> at the specified position in this - * sequence. This sequence is shortened by one <code>char</code>. + * Removes the {@code char} at the specified position in this + * sequence. This sequence is shortened by one {@code char}. * * <p>Note: If the character at the given index is a supplementary * character, this method does not remove the entire character. If * correct handling of supplementary characters is required, - * determine the number of <code>char</code>s to remove by calling - * <code>Character.charCount(thisSequence.codePointAt(index))</code>, - * where <code>thisSequence</code> is this sequence. + * determine the number of {@code char}s to remove by calling + * {@code Character.charCount(thisSequence.codePointAt(index))}, + * where {@code thisSequence} is this sequence. * - * @param index Index of <code>char</code> to remove + * @param index Index of {@code char} to remove * @return This object. - * @throws StringIndexOutOfBoundsException if the <code>index</code> + * @throws StringIndexOutOfBoundsException if the {@code index} * is negative or greater than or equal to - * <code>length()</code>. + * {@code length()}. */ public AbstractStringBuilder deleteCharAt(int index) { if ((index < 0) || (index >= count)) @@ -767,12 +767,12 @@ /** * Replaces the characters in a substring of this sequence - * with characters in the specified <code>String</code>. The substring - * begins at the specified <code>start</code> and extends to the character - * at index <code>end - 1</code> or to the end of the + * with characters in the specified {@code String}. The substring + * begins at the specified {@code start} and extends to the character + * at index {@code end - 1} or to the end of the * sequence if no such character exists. First the * characters in the substring are removed and then the specified - * <code>String</code> is inserted at <code>start</code>. (This + * {@code String} is inserted at {@code start}. (This * sequence will be lengthened to accommodate the * specified String if necessary.) * @@ -780,9 +780,9 @@ * @param end The ending index, exclusive. * @param str String that will replace previous contents. * @return This object. - * @throws StringIndexOutOfBoundsException if <code>start</code> - * is negative, greater than <code>length()</code>, or - * greater than <code>end</code>. + * @throws StringIndexOutOfBoundsException if {@code start} + * is negative, greater than {@code length()}, or + * greater than {@code end}. */ public AbstractStringBuilder replace(int start, int end, String str) { if (start < 0) @@ -805,14 +805,14 @@ } /** - * Returns a new <code>String</code> that contains a subsequence of + * Returns a new {@code String} that contains a subsequence of * characters currently contained in this character sequence. The * substring begins at the specified index and extends to the end of * this sequence. * * @param start The beginning index, inclusive. * @return The new string. - * @throws StringIndexOutOfBoundsException if <code>start</code> is + * @throws StringIndexOutOfBoundsException if {@code start} is * less than zero, or greater than the length of this object. */ public String substring(int start) { @@ -850,18 +850,18 @@ } /** - * Returns a new <code>String</code> that contains a subsequence of + * Returns a new {@code String} that contains a subsequence of * characters currently contained in this sequence. The - * substring begins at the specified <code>start</code> and - * extends to the character at index <code>end - 1</code>. + * substring begins at the specified {@code start} and + * extends to the character at index {@code end - 1}. * * @param start The beginning index, inclusive. * @param end The ending index, exclusive. * @return The new string. - * @throws StringIndexOutOfBoundsException if <code>start</code> - * or <code>end</code> are negative or greater than - * <code>length()</code>, or <code>start</code> is - * greater than <code>end</code>. + * @throws StringIndexOutOfBoundsException if {@code start} + * or {@code end} are negative or greater than + * {@code length()}, or {@code start} is + * greater than {@code end}. */ public String substring(int start, int end) { if (start < 0) @@ -1254,15 +1254,15 @@ * <blockquote><pre> * this.toString().startsWith(str, <i>k</i>) * </pre></blockquote> - * is <code>true</code>. + * is {@code true}. * * @param str any string. * @return if the string argument occurs as a substring within this * object, then the index of the first character of the first * such substring is returned; if it does not occur as a - * substring, <code>-1</code> is returned. - * @throws java.lang.NullPointerException if <code>str</code> is - * <code>null</code>. + * substring, {@code -1} is returned. + * @throws java.lang.NullPointerException if {@code str} is + * {@code null}. */ public int indexOf(String str) { return indexOf(str, 0); @@ -1282,8 +1282,8 @@ * @param fromIndex the index from which to start the search. * @return the index within this string of the first occurrence of the * specified substring, starting at the specified index. - * @throws java.lang.NullPointerException if <code>str</code> is - * <code>null</code>. + * @throws java.lang.NullPointerException if {@code str} is + * {@code null}. */ public int indexOf(String str, int fromIndex) { return String.indexOf(value, 0, count, @@ -1293,7 +1293,7 @@ /** * Returns the index within this string of the rightmost occurrence * of the specified substring. The rightmost empty string "" is - * considered to occur at the index value <code>this.length()</code>. + * considered to occur at the index value {@code this.length()}. * The returned index is the largest value <i>k</i> such that * <blockquote><pre> * this.toString().startsWith(str, k) @@ -1304,9 +1304,9 @@ * @return if the string argument occurs one or more times as a substring * within this object, then the index of the first character of * the last such substring is returned. If it does not occur as - * a substring, <code>-1</code> is returned. - * @throws java.lang.NullPointerException if <code>str</code> is - * <code>null</code>. + * a substring, {@code -1} is returned. + * @throws java.lang.NullPointerException if {@code str} is + * {@code null}. */ public int lastIndexOf(String str) { return lastIndexOf(str, count); @@ -1326,8 +1326,8 @@ * @param fromIndex the index to start the search from. * @return the index within this sequence of the last occurrence of the * specified substring. - * @throws java.lang.NullPointerException if <code>str</code> is - * <code>null</code>. + * @throws java.lang.NullPointerException if {@code str} is + * {@code null}. */ public int lastIndexOf(String str, int fromIndex) { return String.lastIndexOf(value, 0, count, @@ -1342,8 +1342,8 @@ * is never reversed. * * Let <i>n</i> be the character length of this character sequence - * (not the length in <code>char</code> values) just prior to - * execution of the <code>reverse</code> method. Then the + * (not the length in {@code char} values) just prior to + * execution of the {@code reverse} method. Then the * character at index <i>k</i> in the new character sequence is * equal to the character at index <i>n-k-1</i> in the old * character sequence. @@ -1351,7 +1351,7 @@ * <p>Note that the reverse operation may result in producing * surrogate pairs that were unpaired low-surrogates and * high-surrogates before the operation. For example, reversing - * "\uDC00\uD800" produces "\uD800\uDC00" which is + * "\u005CuDC00\u005CuD800" produces "\u005CuD800\u005CuDC00" which is * a valid surrogate pair. * * @return a reference to this object. @@ -1387,11 +1387,11 @@ /** * Returns a string representing the data in this sequence. - * A new <code>String</code> object is allocated and initialized to + * A new {@code String} object is allocated and initialized to * contain the character sequence currently represented by this - * object. This <code>String</code> is then returned. Subsequent + * object. This {@code String} is then returned. Subsequent * changes to this sequence do not affect the contents of the - * <code>String</code>. + * {@code String}. * * @return a string representation of this sequence of characters. */
--- a/jdk/src/share/classes/java/lang/Byte.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/java/lang/Byte.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -110,8 +110,8 @@ * determined by whether {@link java.lang.Character#digit(char, * int)} returns a nonnegative value) except that the first * character may be an ASCII minus sign {@code '-'} - * (<code>'\u002D'</code>) to indicate a negative value or an - * ASCII plus sign {@code '+'} (<code>'\u002B'</code>) to + * ({@code '\u005Cu002D'}) to indicate a negative value or an + * ASCII plus sign {@code '+'} ({@code '\u005Cu002B'}) to * indicate a positive value. The resulting {@code byte} value is * returned. * @@ -127,8 +127,8 @@ * * <li> Any character of the string is not a digit of the * specified radix, except that the first character may be a minus - * sign {@code '-'} (<code>'\u002D'</code>) or plus sign - * {@code '+'} (<code>'\u002B'</code>) provided that the + * sign {@code '-'} ({@code '\u005Cu002D'}) or plus sign + * {@code '+'} ({@code '\u005Cu002B'}) provided that the * string is longer than length 1. * * <li> The value represented by the string is not a value of type @@ -157,9 +157,9 @@ * Parses the string argument as a signed decimal {@code * byte}. The characters in the string must all be decimal digits, * except that the first character may be an ASCII minus sign - * {@code '-'} (<code>'\u002D'</code>) to indicate a negative + * {@code '-'} ({@code '\u005Cu002D'}) to indicate a negative * value or an ASCII plus sign {@code '+'} - * (<code>'\u002B'</code>) to indicate a positive value. The + * ({@code '\u005Cu002B'}) to indicate a positive value. The * resulting {@code byte} value is returned, exactly as if the * argument and the radix 10 were given as arguments to the {@link * #parseByte(java.lang.String, int)} method. @@ -446,6 +446,47 @@ } /** + * Converts the argument to an {@code int} by an unsigned + * conversion. In an unsigned conversion to an {@code int}, the + * high-order 24 bits of the {@code int} are zero and the + * low-order 8 bits are equal to the bits of the {@code byte} argument. + * + * Consequently, zero and positive {@code byte} values are mapped + * to a numerically equal {@code int} value and negative {@code + * byte} values are mapped to an {@code int} value equal to the + * input plus 2<sup>8</sup>. + * + * @param x the value to convert to an unsigned {@code int} + * @return the argument converted to {@code int} by an unsigned + * conversion + * @since 1.8 + */ + public static int toUnsignedInt(byte x) { + return ((int) x) & 0xff; + } + + /** + * Converts the argument to a {@code long} by an unsigned + * conversion. In an unsigned conversion to a {@code long}, the + * high-order 56 bits of the {@code long} are zero and the + * low-order 8 bits are equal to the bits of the {@code byte} argument. + * + * Consequently, zero and positive {@code byte} values are mapped + * to a numerically equal {@code long} value and negative {@code + * byte} values are mapped to a {@code long} value equal to the + * input plus 2<sup>8</sup>. + * + * @param x the value to convert to an unsigned {@code long} + * @return the argument converted to {@code long} by an unsigned + * conversion + * @since 1.8 + */ + public static long toUnsignedLong(byte x) { + return ((long) x) & 0xffL; + } + + + /** * The number of bits used to represent a {@code byte} value in two's * complement binary form. *
--- a/jdk/src/share/classes/java/lang/Double.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/java/lang/Double.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -140,7 +140,7 @@ * <li>Otherwise, the result is a string that represents the sign and * magnitude (absolute value) of the argument. If the sign is negative, * the first character of the result is '{@code -}' - * (<code>'\u002D'</code>); if the sign is positive, no sign character + * ({@code '\u005Cu002D'}); if the sign is positive, no sign character * appears in the result. As for the magnitude <i>m</i>: * <ul> * <li>If <i>m</i> is infinity, it is represented by the characters @@ -156,7 +156,7 @@ * <li>If <i>m</i> is greater than or equal to 10<sup>-3</sup> but less * than 10<sup>7</sup>, then it is represented as the integer part of * <i>m</i>, in decimal form with no leading zeroes, followed by - * '{@code .}' (<code>'\u002E'</code>), followed by one or + * '{@code .}' ({@code '\u005Cu002E'}), followed by one or * more decimal digits representing the fractional part of <i>m</i>. * * <li>If <i>m</i> is less than 10<sup>-3</sup> or greater than or @@ -168,9 +168,9 @@ * 10<sup><i>n</i></sup> so that 1 ≤ <i>a</i> {@literal <} 10. The * magnitude is then represented as the integer part of <i>a</i>, * as a single decimal digit, followed by '{@code .}' - * (<code>'\u002E'</code>), followed by decimal digits + * ({@code '\u005Cu002E'}), followed by decimal digits * representing the fractional part of <i>a</i>, followed by the - * letter '{@code E}' (<code>'\u0045'</code>), followed + * letter '{@code E}' ({@code '\u005Cu0045'}), followed * by a representation of <i>n</i> as a decimal integer, as * produced by the method {@link Integer#toString(int)}. * </ul> @@ -208,7 +208,7 @@ * <li>Otherwise, the result is a string that represents the sign * and magnitude of the argument. If the sign is negative, the * first character of the result is '{@code -}' - * (<code>'\u002D'</code>); if the sign is positive, no sign + * ({@code '\u005Cu002D'}); if the sign is positive, no sign * character appears in the result. As for the magnitude <i>m</i>: * * <ul>
--- a/jdk/src/share/classes/java/lang/Float.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/java/lang/Float.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -138,7 +138,7 @@ * <li>Otherwise, the result is a string that represents the sign and * magnitude (absolute value) of the argument. If the sign is * negative, the first character of the result is - * '{@code -}' (<code>'\u002D'</code>); if the sign is + * '{@code -}' ({@code '\u005Cu002D'}); if the sign is * positive, no sign character appears in the result. As for * the magnitude <i>m</i>: * <ul> @@ -154,7 +154,7 @@ * less than 10<sup>7</sup>, then it is represented as the * integer part of <i>m</i>, in decimal form with no leading * zeroes, followed by '{@code .}' - * (<code>'\u002E'</code>), followed by one or more + * ({@code '\u005Cu002E'}), followed by one or more * decimal digits representing the fractional part of * <i>m</i>. * <li> If <i>m</i> is less than 10<sup>-3</sup> or greater than or @@ -166,10 +166,10 @@ * 10<sup><i>n</i></sup> so that 1 ≤ <i>a</i> {@literal <} 10. * The magnitude is then represented as the integer part of * <i>a</i>, as a single decimal digit, followed by - * '{@code .}' (<code>'\u002E'</code>), followed by + * '{@code .}' ({@code '\u005Cu002E'}), followed by * decimal digits representing the fractional part of * <i>a</i>, followed by the letter '{@code E}' - * (<code>'\u0045'</code>), followed by a representation + * ({@code '\u005Cu0045'}), followed by a representation * of <i>n</i> as a decimal integer, as produced by the * method {@link java.lang.Integer#toString(int)}. * @@ -210,7 +210,7 @@ * <li>Otherwise, the result is a string that represents the sign and * magnitude (absolute value) of the argument. If the sign is negative, * the first character of the result is '{@code -}' - * (<code>'\u002D'</code>); if the sign is positive, no sign character + * ({@code '\u005Cu002D'}); if the sign is positive, no sign character * appears in the result. As for the magnitude <i>m</i>: * * <ul>
--- a/jdk/src/share/classes/java/lang/Integer.java Thu Feb 02 09:39:33 2012 -0800 +++ b/jdk/src/share/classes/java/lang/Integer.java Wed Jul 05 18:01:59 2017 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -93,13 +93,13 @@ * * <p>If the first argument is negative, the first element of the * result is the ASCII minus character {@code '-'} - * (<code>'\u002D'</code>). If the first argument is not + * ({@code '\u005Cu002D'}). If the first argument is not * negative, no sign character appears in the result. * * <p>The remaining characters of the result represent the magnitude * of the first argument. If the magnitude is zero, it is * represented by a single zero character {@code '0'} - * (<code>'\u0030'</code>); otherwise, the first character of + * ({@code '\u005Cu0030'}); otherwise, the first character of * the representation of the magnitude will not be the zero * character. The following ASCII characters are used as digits: * @@ -107,9 +107,9 @@ * {@code 0123456789abcdefghijklmnopqrstuvwxyz} * </blockquote> * - * These are <code>'\u0030'</code> through - * <code>'\u0039'</code> and <code>'\u0061'</code> through - * <code>'\u007A'</code>. If {@code radix} is + * These are {@code '\u005Cu0030'} through + * {@code '\u005Cu0039'} and {@code '\u005Cu0061'} through + * {@code '\u005Cu007A'}. If {@code radix} is * <var>N</var>, then the first <var>N</var> of these characters * are used as radix-<var>N</var> digits in the order shown. Thus, * the digits for hexadecimal (radix 16) are @@ -128,7 +128,6 @@ * @see java.lang.Character#MIN_RADIX */ public static String toString(int i, int radix) { - if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) radix = 10; @@ -159,6 +158,36 @@ } /** + * Returns a string representation of the first argument as an + * unsigned integer value in the radix specified by the second + * argument. + * + * <p>If the radix is smaller than {@code Character.MIN_RADIX} + * or larger than {@code Character.MAX_RADIX}, then the radix + * {@code 10} is used instead. + * + * <p>Note that since the first argument is treated as an unsigned + * value, no leading sign character is printed. + * + * <p>If the magnitude is zero, it is represented by a single zero + * character {@code '0'} ({@code '\u005Cu0030'}); otherwise, + * the first character of the representation of the magnitude will + * not be the zero character. + * + * <p>The behavior of radixes and the characters used as digits + * are the same as {@link #toString(int, int) toString}. + * + * @param i an integer to be converted to an unsigned string. + * @param radix the radix to use in the string representation. + * @return an unsigned string representation of the argument in the specified radix. + * @see #toString(int, int) + * @since 1.8 + */ + public static String toUnsignedString(int i, int radix) { + return Long.toString(toUnsignedLong(i), radix); + } + + /** * Returns a string representation of the integer argument as an * unsigned integer in base 16. * @@ -166,20 +195,26 @@ * if the argument is negative; otherwise, it is equal to the * argument. This value is converted to a string of ASCII digits * in hexadecimal (base 16) with no extra leading - * {@code 0}s. If the unsigned magnitude is zero, it is - * represented by a single zero character {@code '0'} - * (<code>'\u0030'</code>); otherwise, the first character of - * the representation of the unsigned magnitude will not be the - * zero character. The following characters are used as - * hexadecimal digits: + * {@code 0}s. + * + * <p>The value of the argument can be recovered from the returned + * string {@code s} by calling {@link + * Integer#parseUnsignedInt(String, int) + * Integer.parseUnsignedInt(s, 16)}. + * + * <p>If the unsigned magnitude is zero, it is represented by a + * single zero character {@code '0'} ({@code '\u005Cu0030'}); + * otherwise, the first character of the representation of the + * unsigned magnitude will not be the zero character. The + * following characters are used as hexadecimal digits: * * <blockquote> * {@code 0123456789abcdef} * </blockquote> * - * These are the characters <code>'\u0030'</code> through - * <code>'\u0039'</code> and <code>'\u0061'</code> through - * <code>'\u0066'</code>. If uppercase letters are + * These are the characters {@code '\u005Cu0030'} through + * {@code '\u005Cu0039'} and {@code '\u005Cu0061'} through + * {@code '\u005Cu0066'}. If uppercase letters are * desired, the {@link java.lang.String#toUpperCase()} method may * be called on the result: * @@ -190,10 +225,12 @@ * @param i an integer to be converted to a string. * @return the string representation of the unsigned integer value * represented by the argument in hexadecimal (base 16). + * @see #parseUnsignedInt(String, int) + * @see #toUnsignedString(int, int) * @since JDK1.0.2 */ public static String toHexString(int i) { - return toUnsignedString(i, 4); + return toUnsignedString0(i, 4); } /** @@ -205,27 +242,33 @@ * argument. This value is converted to a string of ASCII digits * in octal (base 8) with no extra leading {@code 0}s. * + * <p>The value of the argument can be recovered from the returned + * string {@code s} by calling {@link + * Integer#parseUnsignedInt(String, int) + * Integer.parseUnsignedInt(s, 8)}. + * * <p>If the unsigned magnitude is zero, it is represented by a - * single zero character {@code '0'} - * (<code>'\u0030'</code>); otherwise, the first character of - * the representation of the unsigned magnitude will not be the - * zero character. The following characters are used as octal - * digits: + * single zero character {@code '0'} ({@code '\u005Cu0030'}); + * otherwise, the first character of the representation of the + * unsigned magnitude will not be the zero character. The + * following characters are used as octal digits: * * <blockquote> * {@code 01234567} * </blockquote> * - * These are the characters <code>'\u0030'</code> through - * <code>'\u0037'</code>. + * These are the characters {@code '\u005Cu0030'} through + * {@code '\u005Cu0037'}. * * @param i an integer to be converted to a string. * @return the string representation of the unsigned integer value * represented by the argument in octal (base 8). + * @see #parseUnsignedInt(String, int) + * @see #toUnsignedString(int, int) * @since JDK1.0.2 */ public static String toOctalString(int i) { - return toUnsignedString(i, 3); + return toUnsignedString0(i, 3); } /** @@ -236,27 +279,34 @@ * if the argument is negative; otherwise it is equal to the * argument. This value is converted to a string of ASCII digits * in binary (base 2) with no extra leading {@code 0}s. - * If the unsigned magnitude is zero, it is represented by a - * single zero character {@code '0'} - * (<code>'\u0030'</code>); otherwise, the first character of - * the representation of the unsigned magnitude will not be the - * zero character. The characters {@code '0'} - * (<code>'\u0030'</code>) and {@code '1'} - * (<code>'\u0031'</code>) are used as binary digits. + * + * <p>The value of the argument can be recovered from the returned + * string {@code s} by calling {@link + * Integer#parseUnsignedInt(String, int) + * Integer.parseUnsignedInt(s, 2)}. + * + * <p>If the unsigned magnitude is zero, it is represented by a + * single zero character {@code '0'} ({@code '\u005Cu0030'}); + * otherwise, the first character of the representation of the + * unsigned magnitude will not be the zero character. The + * characters {@code '0'} ({@code '\u005Cu0030'}) and {@code + * '1'} ({@code '\u005Cu0031'}) are used as binary digits. * * @param i an integer to be converted to a string. * @return the string representation of the unsigned integer value * represented by the argument in binary (base 2). + * @see #parseUnsignedInt(String, int) + * @see #toUnsignedString(int, int) * @since JDK1.0.2 */ public static String toBinaryString(int i) { - return toUnsignedString(i, 1); + return toUnsignedString0(i, 1); } /** * Convert the integer to an unsigned number. */ - private static String toUnsignedString(int i, int shift) { + private static String toUnsignedString0(int i, int shift) { char[] buf = new char[32]; int charPos = 32; int radix = 1 << shift; @@ -335,6 +385,24 @@ } /** + * Returns a string representation of the argument as an unsigned + * decimal value. + * + * The argument is converted to unsigned decimal representation + * and returned as a string exactly as if the argument and radix + * 10 were given as arguments to the {@link #toUnsignedString(int, + * int)} method. + * + * @param i an integer to be converted to an unsigned string. + * @return an unsigned string representation of the argument. + * @see #toUnsignedString(int, int) + * @since 1.8 + */